diff --git a/src/add-ons/screen_savers/Jamfile b/src/add-ons/screen_savers/Jamfile index 8c9a3b7b21..0564ffce69 100644 --- a/src/add-ons/screen_savers/Jamfile +++ b/src/add-ons/screen_savers/Jamfile @@ -1,10 +1,12 @@ SubDir HAIKU_TOP src add-ons screen_savers ; +SubInclude HAIKU_TOP src add-ons screen_savers butterfly ; SubInclude HAIKU_TOP src add-ons screen_savers debugnow ; SubInclude HAIKU_TOP src add-ons screen_savers flurry ; SubInclude HAIKU_TOP src add-ons screen_savers haiku ; SubInclude HAIKU_TOP src add-ons screen_savers icons ; SubInclude HAIKU_TOP src add-ons screen_savers ifs ; +SubInclude HAIKU_TOP src add-ons screen_savers leaves ; SubInclude HAIKU_TOP src add-ons screen_savers message ; SubInclude HAIKU_TOP src add-ons screen_savers simpleclock ; SubInclude HAIKU_TOP src add-ons screen_savers slideshowsaver ; diff --git a/src/add-ons/screen_savers/butterfly/Butterfly.cpp b/src/add-ons/screen_savers/butterfly/Butterfly.cpp new file mode 100644 index 0000000000..09086ad7a3 --- /dev/null +++ b/src/add-ons/screen_savers/butterfly/Butterfly.cpp @@ -0,0 +1,161 @@ +/* + * Copyright 2010-2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Geoffry Song, goffrie@gmail.com + */ +#include "Butterfly.h" + +#include +#include +#include + +#include + +#include + + +const float kOneSixth = 0.1666666666666666666f; // 1/2 * 1/3 + + +extern "C" BScreenSaver* +instantiate_screen_saver(BMessage* archive, image_id imageId) +{ + return new Butterfly(archive, imageId); +} + + +Butterfly::Butterfly(BMessage* archive, image_id imageId) + : BScreenSaver(archive, imageId) +{ +} + + +void +Butterfly::StartConfig(BView* view) +{ + BPrivate::BuildScreenSaverDefaultSettingsView(view, "Butterfly", + "by Geoffry Song"); +} + + +status_t +Butterfly::StartSaver(BView* view, bool preview) +{ + view->SetLowColor(0, 0, 0); + view->FillRect(view->Bounds(), B_SOLID_LOW); + view->SetDrawingMode(B_OP_ALPHA); + view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); + view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN); + if (!preview) + view->SetPenSize(2.0); + + SetTickSize(20000); + + struct timeval tv; + gettimeofday(&tv, NULL); + fT = tv.tv_usec * 0.01f; + + // calculate transformation + BRect bounds = view->Bounds(); + fScale = MIN(bounds.Width(), bounds.Height()) * 0.1f; + fTrans.Set(bounds.Width() * 0.5f, bounds.Height() * 0.5f); + fBounds = bounds; + + fLast[0] = _Iterate(); + fLast[1] = _Iterate(); + fLast[2] = _Iterate(); + + return B_OK; +} + + +void +Butterfly::Draw(BView* view, int32 frame) +{ + if (frame == 1024) { + // calculate bounding box ( (-5.92,-5.92) to (5.92, 5.92) ) + fBounds.Set(-5.92 * fScale + fTrans.x, -5.92 * fScale + fTrans.y, + 5.92 * fScale + fTrans.x, 5.92 * fScale + fTrans.y); + } + if ((frame & 3) == 0) { + // fade out + view->SetHighColor(0, 0, 0, 4); + view->FillRect(fBounds); + } + // create a color from a hue of (fT * 15) degrees + view->SetHighColor(_HueToColor(fT * 15.f)); + BPoint p = _Iterate(); + + // cubic Hermite interpolation from fLast[1] to fLast[2] + // calculate tangents for a Catmull-Rom spline + //(these values need to be halved) + BPoint m1 = fLast[2] - fLast[0]; // tangent for fLast[1] + BPoint m2 = p - fLast[1]; // tangent for fLast[2] + + // draw Bezier from fLast[1] to fLast[2] with control points + // fLast[1] + m1/3, fLast[2] - m2/3 + m1.x *= kOneSixth; + m1.y *= kOneSixth; + m2.x *= kOneSixth; + m2.y *= kOneSixth; + BPoint control[4] = { fLast[1], fLast[1] + m1, fLast[2] - m2, fLast[2] }; + view->StrokeBezier(control); + + fLast[0] = fLast[1]; + fLast[1] = fLast[2]; + fLast[2] = p; +} + + +// convert from a hue in degrees to a fully saturated color +inline rgb_color +Butterfly::_HueToColor(float hue) +{ + // convert from [0..360) to [0..1530) + int h = static_cast(fmodf(hue, 360) * 4.25f); + int x = 255 - abs(h % 510 - 255); + + rgb_color result = {0, 0, 0, 255}; + if (h < 255) { + result.red = 255; + result.green = x; + } else if (h < 510) { + result.red = x; + result.green = 255; + } else if (h < 765) { + result.green = 255; + result.blue = x; + } else if (h < 1020) { + result.green = x; + result.blue = 255; + } else if (h < 1275) { + result.red = x; + result.blue = 255; + } else { + result.red = 255; + result.blue = x; + } + return result; +} + + +inline BPoint +Butterfly::_Iterate() +{ + float r = powf(2.718281828f, cosf(fT)) + - 2.f * cosf(4.f * fT) + - powf(sinf(fT / 12.f), 5.f); + // rotate and move it a bit + BPoint p(sinf(fT * 1.01f) * r + cosf(fT * 1.02f) * 0.2f, + cosf(fT * 1.01f) * r + sinf(fT * 1.02f) * 0.2f); + // transform to view coordinates + p.x *= fScale; + p.y *= fScale; + p += fTrans; + // move on + fT += 0.05f; + return p; +} + diff --git a/src/add-ons/screen_savers/butterfly/Butterfly.h b/src/add-ons/screen_savers/butterfly/Butterfly.h new file mode 100644 index 0000000000..4a6af85ff7 --- /dev/null +++ b/src/add-ons/screen_savers/butterfly/Butterfly.h @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Geoffry Song, goffrie@gmail.com + */ +#ifndef _BUTTERFLY_H_ +#define _BUTTERFLY_H_ + + +#include + + +class Butterfly : public BScreenSaver { +public: + Butterfly(BMessage* archive, image_id imageId); + + virtual void StartConfig(BView* view); + virtual status_t StartSaver(BView* view, bool preview); + virtual void Draw(BView* view, int32 frame); + +private: + float fT; + // previously calculated points + BPoint fLast[3]; + // transformation from graph coordinates to view coordinates + float fScale; + BPoint fTrans; + // bounding box of drawn figure + BRect fBounds; + + inline rgb_color _HueToColor(float hue); + inline BPoint _Iterate(); +}; + +#endif // _BUTTERFLY_H_ + diff --git a/src/add-ons/screen_savers/butterfly/Jamfile b/src/add-ons/screen_savers/butterfly/Jamfile new file mode 100644 index 0000000000..e321c0ef21 --- /dev/null +++ b/src/add-ons/screen_savers/butterfly/Jamfile @@ -0,0 +1,9 @@ +SubDir HAIKU_TOP src add-ons screen_savers butterfly ; + +UsePrivateHeaders screen_saver ; + # For BuildScreenSaverDefaultSettingsView + +ScreenSaver Butterfly : + Butterfly.cpp : + be screensaver $(TARGET_LIBSUPC++) ; + diff --git a/src/add-ons/screen_savers/leaves/Jamfile b/src/add-ons/screen_savers/leaves/Jamfile new file mode 100644 index 0000000000..6df2c6dc72 --- /dev/null +++ b/src/add-ons/screen_savers/leaves/Jamfile @@ -0,0 +1,6 @@ +SubDir HAIKU_TOP src add-ons screen_savers leaves ; + +ScreenSaver Leaves : + Leaves.cpp : + be screensaver $(TARGET_LIBSUPC++) ; + diff --git a/src/add-ons/screen_savers/leaves/Leaves.cpp b/src/add-ons/screen_savers/leaves/Leaves.cpp new file mode 100644 index 0000000000..089e3c95c5 --- /dev/null +++ b/src/add-ons/screen_savers/leaves/Leaves.cpp @@ -0,0 +1,243 @@ +/* + * Copyright 2010-2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * Deyan Genovski, deangenovski@gmail.com + * Geoffry Song, goffrie@gmail.com + */ +#include "Leaves.h" + +#include +#include + +#include +#include +#include +#include +#include + + +// path data for the leaf shape +static const BPoint kLeafBegin(56.24793f, 15.46287f); +static BPoint kLeafCurves[][3] = { + { BPoint(61.14, 28.89), BPoint(69.78, 38.25), BPoint(83.48, 44.17) }, + { BPoint(99.46, 37.52), BPoint(113.27, 29.61), BPoint(134.91, 30.86) }, + { BPoint(130.58, 36.53), BPoint(126.74, 42.44), BPoint(123.84, 48.81) }, + { BPoint(131.81, 42.22), BPoint(137.53, 38.33), BPoint(144.37, 33.10) }, + { BPoint(169.17, 23.55), BPoint(198.90, 15.55), BPoint(232.05, 10.51) }, + { BPoint(225.49, 18.37), BPoint(219.31, 28.17), BPoint(217.41, 40.24) }, + { BPoint(227.70, 26.60), BPoint(239.97, 14.63), BPoint(251.43, 8.36) }, + { BPoint(288.89, 9.12), BPoint(322.73, 14.33), BPoint(346.69, 31.67) }, + { BPoint(330.49, 37.85), BPoint(314.36, 44.25), BPoint(299.55, 54.17) }, + { BPoint(292.48, 52.54), BPoint(289.31, 49.70), BPoint(285.62, 47.03) }, + { BPoint(283.73, 54.61), BPoint(284.46, 57.94), BPoint(285.62, 60.60) }, + { BPoint(259.78, 76.14), BPoint(233.24, 90.54), BPoint(202.41, 98.10) }, + { BPoint(194.43, 95.36), BPoint(185.96, 92.39), BPoint(179.63, 88.33) }, + { BPoint(180.15, 94.75), BPoint(182.73, 99.76), BPoint(185.62, 104.53) }, + { BPoint(154.83, 119.46), BPoint(133.21, 118.97), BPoint(125.62, 94.88) }, + { BPoint(124.70, 98.79), BPoint(124.11, 103.67), BPoint(124.19, 110.60) }, + { BPoint(116.42, 111.81), BPoint(85.82, 99.60), BPoint(83.25, 51.96) }, + { BPoint(62.50, 42.57), BPoint(58.12, 33.18), BPoint(50.98, 23.81) } }; +static const int kLeafCurveCount = sizeof(kLeafCurves) / sizeof(kLeafCurves[0]); +static const float kLeafWidth = 372.f; +static const float kLeafHeight = 121.f; + +// leaf colors +static const rgb_color kColors[][2] = { + { {255, 114, 0, 255}, {255, 159, 0, 255} }, + { {50, 160, 40, 255}, {125, 210, 32, 255} }, + { {250, 190, 30, 255}, {255, 214, 125, 255} } }; +static const int kColorCount = sizeof(kColors) / sizeof(kColors[0]); + +// bounds for settings +static const int kMinimumDropRate = 2, kMaximumDropRate = 50; +static const int kMinimumLeafSize = 50, kMaximumLeafSize = 1000; +static const int kMaximumSizeVariation = 200; + +enum { + MSG_SET_DROP_RATE = 'drop', + MSG_SET_LEAF_SIZE = 'size', + MSG_SET_SIZE_VARIATION = 'svry', +}; + + +extern "C" BScreenSaver* +instantiate_screen_saver(BMessage* msg, image_id image) +{ + return new Leaves(msg, image); +} + + +Leaves::Leaves(BMessage* archive, image_id id) + : + BScreenSaver(archive, id), + fDropRateSlider(NULL), + fLeafSizeSlider(NULL), + fSizeVariationSlider(NULL), + fDropRate(10), + fLeafSize(150), + fSizeVariation(50) +{ + if (archive) { + if (archive->FindInt32("Leaves drop rate", &fDropRate) != B_OK) + fDropRate = 10; + if (archive->FindInt32("Leaves size", &fLeafSize) != B_OK) + fLeafSize = 150; + if (archive->FindInt32("Leaves variation", &fSizeVariation) != B_OK) + fSizeVariation = 50; + } +} + + +void +Leaves::StartConfig(BView* view) +{ + BRect bounds = view->Bounds(); + bounds.InsetBy(10, 10); + BRect frame(0, 0, bounds.Width(), 20); + + fDropRateSlider = new BSlider(frame, "drop rate", "Drop rate:", + new BMessage(MSG_SET_DROP_RATE), kMinimumDropRate, kMaximumDropRate, + B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); + fDropRateSlider->SetValue(fDropRate); + fDropRateSlider->ResizeToPreferred(); + bounds.bottom -= fDropRateSlider->Bounds().Height() * 1.5; + fDropRateSlider->MoveTo(bounds.LeftBottom()); + view->AddChild(fDropRateSlider); + + fLeafSizeSlider = new BSlider(frame, "leaf size", "Leaf size:", + new BMessage(MSG_SET_LEAF_SIZE), kMinimumLeafSize, kMaximumLeafSize, + B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); + fLeafSizeSlider->SetValue(fLeafSize); + fLeafSizeSlider->ResizeToPreferred(); + bounds.bottom -= fLeafSizeSlider->Bounds().Height() * 1.5; + fLeafSizeSlider->MoveTo(bounds.LeftBottom()); + view->AddChild(fLeafSizeSlider); + + fSizeVariationSlider = new BSlider(frame, "variation", "Size variation:", + new BMessage(MSG_SET_SIZE_VARIATION), 0, kMaximumSizeVariation, + B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); + fSizeVariationSlider->SetValue(fSizeVariation); + fSizeVariationSlider->ResizeToPreferred(); + bounds.bottom -= fSizeVariationSlider->Bounds().Height() * 1.5; + fSizeVariationSlider->MoveTo(bounds.LeftBottom()); + view->AddChild(fSizeVariationSlider); + + BTextView* textView = new BTextView(bounds, B_EMPTY_STRING, + bounds.OffsetToCopy(0., 0.), B_FOLLOW_ALL, B_WILL_DRAW); + textView->SetViewColor(view->ViewColor()); + textView->Insert("Leaves\n\n" + "by Deyan Genovski, Geoffry Song\n\n"); + textView->SetStylable(true); + textView->SetFontAndColor(0, 6, be_bold_font); + textView->MakeEditable(false); + view->AddChild(textView); + + BWindow* window = view->Window(); + if (window) window->AddHandler(this); + + fDropRateSlider->SetTarget(this); + fLeafSizeSlider->SetTarget(this); + fSizeVariationSlider->SetTarget(this); +} + + +status_t +Leaves::StartSaver(BView* view, bool preview) +{ + SetTickSize(10000000 / fDropRate); + srand48(time(NULL)); + + view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN); + + return B_OK; +} + + +status_t +Leaves::SaveState(BMessage* into) const +{ + status_t status; + if ((status = into->AddInt32("Leaves drop rate", fDropRate)) != B_OK) + return status; + if ((status = into->AddInt32("Leaves size", fLeafSize)) != B_OK) + return status; + if ((status = into->AddInt32("Leaves variation", fSizeVariation)) != B_OK) + return status; + return B_OK; +} + + +void +Leaves::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_SET_DROP_RATE: + fDropRate = fDropRateSlider->Value(); + break; + case MSG_SET_LEAF_SIZE: + fLeafSize = fLeafSizeSlider->Value(); + break; + case MSG_SET_SIZE_VARIATION: + fSizeVariation = fSizeVariationSlider->Value(); + break; + default: + BHandler::MessageReceived(message); + } +} + + +void +Leaves::Draw(BView* view, int32 frame) +{ + float scale = fLeafSize / kLeafWidth / (kMaximumLeafSize * 2); + scale *= view->Bounds().Width(); + scale += scale * drand48() * fSizeVariation / 100.; + + BAffineTransform transform; + transform.TranslateBy(-kLeafWidth / 2, -kLeafHeight / 2); + // draw the leaf centered on the point + transform.RotateBy(drand48() * 2. * M_PI); + if ((rand() & 64) == 0) transform.ScaleBy(-1., 1.); + // flip half of the time + transform.ScaleBy(scale); + transform.TranslateBy(_RandomPoint(view->Bounds())); + + BPoint center = transform.Apply(BPoint(kLeafWidth / 2, kLeafHeight / 2)); + BPoint gradientOffset = BPoint(60 * scale, 80 * scale); + BGradientLinear gradient(center - gradientOffset, center + gradientOffset); + int color = (rand() / 7) % kColorCount; + gradient.AddColor(kColors[color][0], 0.f); + gradient.AddColor(kColors[color][1], 255.f); + + BShape leafShape; + leafShape.MoveTo(transform.Apply(kLeafBegin)); + for (int i = 0; i < kLeafCurveCount; ++i) { + BPoint control[3]; + for (int j = 0; j < 3; ++j) + control[j] = transform.Apply(kLeafCurves[i][j]); + leafShape.BezierTo(control); + } + leafShape.Close(); + + view->PushState(); + view->SetDrawingMode(B_OP_ALPHA); + view->SetHighColor(0, 0, 0, 50); + for (int i = 2; i >= 0; --i) { + view->SetOrigin(i * 0.1, i * 0.3); + view->SetPenSize(i * 2); + view->StrokeShape(&leafShape); + } + view->PopState(); + view->FillShape(&leafShape, gradient); +} + + +inline BPoint +Leaves::_RandomPoint(const BRect& bound) +{ + return BPoint(drand48() * (bound.right - bound.left) + bound.left, + drand48() * (bound.bottom - bound.top) + bound.top); +} + diff --git a/src/add-ons/screen_savers/leaves/Leaves.h b/src/add-ons/screen_savers/leaves/Leaves.h new file mode 100644 index 0000000000..cb5c2560b3 --- /dev/null +++ b/src/add-ons/screen_savers/leaves/Leaves.h @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * Geoffry Song, goffrie@gmail.com + */ +#ifndef _LEAVES_H_ +#define _LEAVES_H_ + + +#include + +#include + + +class BSlider; + +class Leaves : public BScreenSaver, public BHandler { +public: + Leaves(BMessage* archive, image_id id); + virtual void Draw(BView* view, int32 frame); + virtual void StartConfig(BView* view); + virtual status_t StartSaver(BView* view, bool preview); + + virtual status_t SaveState(BMessage* into) const; + + virtual void MessageReceived(BMessage* message); + +private: + BSlider* fDropRateSlider; + BSlider* fLeafSizeSlider; + BSlider* fSizeVariationSlider; + int32 fDropRate; + int32 fLeafSize; + int32 fSizeVariation; + + inline BPoint _RandomPoint(const BRect& bound); +}; + +#endif // _LEAVES_H_ +