mirror of
https://projects.vdr-developer.org/git/vdr-plugin-skindesigner.git
synced 2023-10-19 17:58:31 +02:00
365 lines
10 KiB
C
365 lines
10 KiB
C
#include "animation.h"
|
|
#include <math.h>
|
|
|
|
/******************************************************************
|
|
* cAnimation
|
|
******************************************************************/
|
|
cAnimation::cAnimation(cScrollable *scrollable) : cThread("scroller") {
|
|
this->scrollable = scrollable;
|
|
this->detachable = NULL;
|
|
this->fadable = NULL;
|
|
this->shiftable = NULL;
|
|
this->blinkable = NULL;
|
|
waitOnWakeup = false;
|
|
keepSleeping = false;
|
|
doAnimation = true;
|
|
modeIn = false;
|
|
blinkFunc = -1;
|
|
}
|
|
|
|
cAnimation::cAnimation(cDetachable *detachable, bool wait, bool animation) : cThread("detached") {
|
|
this->scrollable = NULL;
|
|
this->detachable = detachable;
|
|
this->fadable = NULL;
|
|
this->shiftable = NULL;
|
|
this->blinkable = NULL;
|
|
waitOnWakeup = wait;
|
|
keepSleeping = false;
|
|
doAnimation = animation;
|
|
modeIn = false;
|
|
blinkFunc = -1;
|
|
}
|
|
|
|
cAnimation::cAnimation(cFadable *fadable, bool fadein) : cThread("fadable") {
|
|
this->scrollable = NULL;
|
|
this->detachable = NULL;
|
|
this->fadable = fadable;
|
|
this->shiftable = NULL;
|
|
this->blinkable = NULL;
|
|
waitOnWakeup = false;
|
|
keepSleeping = false;
|
|
doAnimation = true;
|
|
modeIn = fadein;
|
|
blinkFunc = -1;
|
|
}
|
|
|
|
cAnimation::cAnimation(cShiftable *shiftable, cPoint &start, cPoint &end, bool shiftin) : cThread("shiftable") {
|
|
this->scrollable = NULL;
|
|
this->detachable = NULL;
|
|
this->fadable = NULL;
|
|
this->shiftable = shiftable;
|
|
this->blinkable = NULL;
|
|
waitOnWakeup = false;
|
|
keepSleeping = false;
|
|
doAnimation = true;
|
|
modeIn = shiftin;
|
|
shiftstart = start;
|
|
shiftend = end;
|
|
blinkFunc = -1;
|
|
}
|
|
|
|
cAnimation::cAnimation(cBlinkable *blinkable, int func) : cThread("blinking") {
|
|
this->scrollable = NULL;
|
|
this->detachable = NULL;
|
|
this->fadable = NULL;
|
|
this->shiftable = NULL;
|
|
this->blinkable = blinkable;
|
|
waitOnWakeup = false;
|
|
keepSleeping = false;
|
|
doAnimation = true;
|
|
modeIn = false;
|
|
blinkFunc = func;
|
|
}
|
|
|
|
cAnimation::~cAnimation(void) {
|
|
sleepWait.Signal();
|
|
Cancel(2);
|
|
}
|
|
|
|
void cAnimation::WakeUp(void) {
|
|
sleepWait.Signal();
|
|
}
|
|
|
|
void cAnimation::ResetSleep(void) {
|
|
keepSleeping = true;
|
|
sleepWait.Signal();
|
|
}
|
|
|
|
void cAnimation::Stop(bool deletePixmaps) {
|
|
sleepWait.Signal();
|
|
Cancel(2);
|
|
if (scrollable && deletePixmaps)
|
|
scrollable->StopScrolling();
|
|
}
|
|
|
|
void cAnimation::Action(void) {
|
|
if (scrollable) {
|
|
Scroll();
|
|
} else if (detachable) {
|
|
Detach();
|
|
} else if (fadable) {
|
|
Fade();
|
|
} else if (shiftable) {
|
|
Shift();
|
|
} else if (blinkable) {
|
|
Blink();
|
|
}
|
|
}
|
|
|
|
void cAnimation::Sleep(int duration) {
|
|
//sleep should wake up itself, so no infinit wait allowed
|
|
if (duration <= 0)
|
|
return;
|
|
do {
|
|
keepSleeping = false;
|
|
sleepWait.Wait(duration);
|
|
} while (keepSleeping);
|
|
}
|
|
|
|
void cAnimation::Wait(void) {
|
|
//wait has to be waked up from outside
|
|
sleepWait.Wait(0);
|
|
}
|
|
|
|
void cAnimation::Scroll(void) {
|
|
int delay = scrollable->ScrollDelay();
|
|
Sleep(delay);
|
|
if (!Running()) return;
|
|
|
|
eOrientation orientation = scrollable->ScrollOrientation();
|
|
int scrollTotal = 0;
|
|
if (orientation == eOrientation::horizontal) {
|
|
scrollTotal = scrollable->ScrollWidth();
|
|
} else if (orientation == eOrientation::vertical) {
|
|
scrollTotal = scrollable->ScrollHeight();
|
|
}
|
|
|
|
eScrollMode mode = scrollable->ScrollMode();
|
|
bool carriageReturn = (mode == eScrollMode::carriagereturn) ? true : false;
|
|
|
|
eScrollSpeed speed = scrollable->ScrollSpeed();
|
|
int frameTime = 30;
|
|
if (speed == eScrollSpeed::slow)
|
|
frameTime = 50;
|
|
else if (speed == eScrollSpeed::medium)
|
|
frameTime = 30;
|
|
else if (speed == eScrollSpeed::fast)
|
|
frameTime = 15;
|
|
|
|
if (!Running()) return;
|
|
|
|
scrollable->StartScrolling();
|
|
|
|
int drawPortX = 0;
|
|
int drawPortY = 0;
|
|
int scrollDelta = 1;
|
|
|
|
bool doSleep = false;
|
|
while (Running()) {
|
|
if (doSleep) {
|
|
Sleep(delay);
|
|
doSleep = false;
|
|
}
|
|
if (!Running()) return;
|
|
uint64_t now = cTimeMs::Now();
|
|
|
|
cPoint drawPortPoint(0,0);
|
|
if (orientation == eOrientation::horizontal) {
|
|
|
|
drawPortX -= scrollDelta;
|
|
if (abs(drawPortX) > scrollTotal) {
|
|
Sleep(delay);
|
|
if (carriageReturn) {
|
|
drawPortX = 0;
|
|
doSleep = true;
|
|
} else {
|
|
scrollDelta *= -1;
|
|
drawPortX -= scrollDelta;
|
|
}
|
|
}
|
|
drawPortPoint.SetX(drawPortX);
|
|
|
|
} else if (orientation == eOrientation::vertical) {
|
|
|
|
drawPortY -= scrollDelta;
|
|
if (abs(drawPortY) > scrollTotal) {
|
|
Sleep(delay);
|
|
drawPortY = 0;
|
|
doSleep = true;
|
|
}
|
|
drawPortPoint.SetY(drawPortY);
|
|
|
|
}
|
|
|
|
if (!Running()) return;
|
|
scrollable->SetDrawPort(drawPortPoint);
|
|
|
|
if (!Running()) return;
|
|
scrollable->Flush();
|
|
|
|
if (orientation == eOrientation::horizontal && !carriageReturn && (drawPortX == 0)) {
|
|
scrollDelta *= -1;
|
|
doSleep = true;
|
|
}
|
|
|
|
int delta = cTimeMs::Now() - now;
|
|
if (delta < frameTime)
|
|
Sleep(frameTime - delta);
|
|
}
|
|
}
|
|
|
|
void cAnimation::Detach(void) {
|
|
if (waitOnWakeup) {
|
|
Wait();
|
|
int delay = 50 + detachable->Delay();
|
|
Sleep(delay);
|
|
} else {
|
|
int delay = detachable->Delay();
|
|
if (delay > 0)
|
|
Sleep(delay);
|
|
}
|
|
if (!Running()) return;
|
|
detachable->ParseDetached();
|
|
if (!Running()) return;
|
|
detachable->RenderDetached();
|
|
if (!Running()) return;
|
|
if (!doAnimation)
|
|
detachable->Flush();
|
|
if (!Running()) return;
|
|
if (doAnimation) {
|
|
detachable->StartAnimation();
|
|
}
|
|
}
|
|
|
|
void cAnimation::Fade(void) {
|
|
int fadetime = fadable->FadeTime();
|
|
int frametime = 1000 / FPS;
|
|
int step = 100.0f / ((double)fadetime / (double)frametime);
|
|
uint64_t start = cTimeMs::Now();
|
|
int transparency = 0;
|
|
if (modeIn) {
|
|
transparency = 100 - step;
|
|
} else {
|
|
transparency = step;
|
|
}
|
|
//wait configured delay if not already done by detacher
|
|
if (!fadable->Detached()) {
|
|
int delay = fadable->Delay();
|
|
if (delay > 0)
|
|
Sleep(delay);
|
|
}
|
|
while (Running() || !modeIn) {
|
|
uint64_t now = cTimeMs::Now();
|
|
if (Running() || !modeIn)
|
|
fadable->SetTransparency(transparency, !modeIn);
|
|
if (Running() || !modeIn)
|
|
fadable->Flush();
|
|
int delta = cTimeMs::Now() - now;
|
|
if ((Running() || !modeIn) && (delta < frametime)) {
|
|
Sleep(frametime - delta);
|
|
}
|
|
if ((int)(now - start) > fadetime) {
|
|
if ((Running() && modeIn) && transparency > 0) {
|
|
fadable->SetTransparency(0);
|
|
fadable->Flush();
|
|
} else if (!modeIn && transparency < 100) {
|
|
fadable->SetTransparency(100, true);
|
|
fadable->Flush();
|
|
}
|
|
break;
|
|
}
|
|
if (modeIn) {
|
|
transparency -= step;
|
|
if (transparency < 0)
|
|
transparency = 0;
|
|
} else {
|
|
transparency += step;
|
|
if (transparency > 100)
|
|
transparency = 100;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cAnimation::Shift(void) {
|
|
int shifttime = shiftable->ShiftTime();
|
|
eShiftMode mode = (eShiftMode)shiftable->ShiftMode();
|
|
//in shiftmode slowedDown shifting is done starting with slowratio % faster
|
|
//at start. Then speed reduces linear to (100 - slowratio)% at end
|
|
//for me 60 is a nice value :-)
|
|
int slowRatio = 60;
|
|
|
|
int frametime = 1000 / FPS;
|
|
int steps = (double)shifttime / (double)frametime;
|
|
if (steps < 2)
|
|
return;
|
|
int stepXLinear = 0;
|
|
int stepYLinear = 0;
|
|
if (shiftstart.X() == shiftend.X()) {
|
|
stepYLinear = (shiftend.Y() - shiftstart.Y()) / steps;
|
|
} else if (shiftstart.Y() == shiftend.Y()) {
|
|
stepXLinear = (shiftend.X() - shiftstart.X()) / steps;
|
|
} else {
|
|
stepXLinear = (shiftend.X() - shiftstart.X()) / steps;
|
|
stepYLinear = (shiftend.Y() - shiftstart.Y()) / steps;
|
|
}
|
|
int stepX = stepXLinear;
|
|
int stepY = stepYLinear;
|
|
|
|
cPoint pos;
|
|
if (modeIn)
|
|
pos = shiftstart;
|
|
else
|
|
pos = shiftend;
|
|
|
|
//wait configured delay if not already done by detacher
|
|
if (!shiftable->Detached()) {
|
|
int delay = shiftable->Delay();
|
|
if (delay > 0)
|
|
Sleep(delay);
|
|
}
|
|
uint64_t start = cTimeMs::Now();
|
|
while (Running() || !modeIn) {
|
|
uint64_t now = cTimeMs::Now();
|
|
if (Running() || !modeIn)
|
|
shiftable->SetPosition(pos, shiftend);
|
|
if (Running() || !modeIn)
|
|
shiftable->Flush();
|
|
int delta = cTimeMs::Now() - now;
|
|
if ((Running() || !modeIn) && (delta < frametime)) {
|
|
cCondWait::SleepMs(frametime - delta);
|
|
}
|
|
if ((int)(now - start) > shifttime) {
|
|
if ((Running() && modeIn) && pos != shiftend) {
|
|
shiftable->SetPosition(shiftend, shiftend);
|
|
shiftable->Flush();
|
|
}
|
|
break;
|
|
}
|
|
if (mode == eShiftMode::slowedDown) {
|
|
double t = (double)(now - start) / (double)shifttime;
|
|
double factor = 1.0f + (double)slowRatio / 100.0f - 2.0f * ((double)slowRatio / 100.0f) * t;
|
|
stepX = stepXLinear * factor;
|
|
stepY = stepYLinear * factor;
|
|
}
|
|
if (modeIn) {
|
|
pos.Set(pos.X() + stepX, pos.Y() + stepY);
|
|
} else {
|
|
pos.Set(pos.X() - stepX, pos.Y() - stepY);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void cAnimation::Blink(void) {
|
|
int freq = blinkable->BlinkFreq(blinkFunc);
|
|
bool blinkOn = false;
|
|
while (Running()) {
|
|
Sleep(freq);
|
|
if (Running())
|
|
blinkable->DoBlink(blinkFunc, blinkOn);
|
|
if (Running())
|
|
blinkable->Flush();
|
|
blinkOn = !blinkOn;
|
|
}
|
|
}
|