* Copyright 2010-2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Geoffry Song, goffrie@gmail.com
* Ryan Leavengood, leavengood@gmail.com
*/
#include "Butterfly.h"
#include <math.h>
#include <stdlib.h>
#include <Catalog.h>
#include <DefaultSettingsView.h>
#include <OS.h>
#include <View.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Screensaver Butterfly"
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::BuildDefaultSettingsView(view, "Butterfly",
B_TRANSLATE("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);
srand48(system_time());
fBase = drand48() * 2 * M_PI * 1000;
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) {
fBounds.Set(-5.92f * fScale + fTrans.x, -5.92f * fScale + fTrans.y,
5.92f * fScale + fTrans.x, 5.92f * fScale + fTrans.y);
}
if ((frame & 3) == 0) {
view->SetHighColor(0, 0, 0, 4);
view->FillRect(fBounds);
}
view->SetHighColor(_HueToColor(fBase * 15));
BPoint p = _Iterate();
BPoint m1 = fLast[2] - fLast[0];
BPoint m2 = p - fLast[1];
m1.x /= 6;
m1.y /= 6;
m2.x /= 6;
m2.y /= 6;
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;
}
inline rgb_color
Butterfly::_HueToColor(float hue)
{
int h = static_cast<int>(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(M_E, cosf(fBase)) - 2 * cosf(4 * fBase)
- powf(sinf(fBase / 12), 5);
BPoint p(sinf(fBase * 1.01f) * r + cosf(fBase * 1.02f) * 0.2f,
cosf(fBase * 1.01f) * r + sinf(fBase * 1.02f) * 0.2f);
p.x *= fScale;
p.y *= fScale;
p += fTrans;
fBase += 0.05f;
return p;
}