...
This commit is contained in:
parent
af80e71d17
commit
167c433a59
@ -1,5 +1,236 @@
|
||||
//
|
||||
// Created by JIBUM HAN on 2025. 8. 28..
|
||||
//
|
||||
|
||||
#include "AnimationStrategy.h"
|
||||
#include "Renderer.h" // Renderer의 그리기 헬퍼 함수들을 사용하기 위해 포함
|
||||
#include <algorithm> // for std::max, std::clamp
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
|
||||
// ====================================================================
|
||||
// --- PAN (왕복 이동) 애니메이션 ---
|
||||
// ====================================================================
|
||||
class PanAnimation : public AnimationStrategy {
|
||||
public:
|
||||
PanAnimation(float speed) : AnimationStrategy(speed) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
offsetX_ = 0.0f;
|
||||
offsetY_ = 0.0f;
|
||||
cycleComplete_ = false;
|
||||
xDirection_ = 1;
|
||||
yDirection_ = 1;
|
||||
}
|
||||
|
||||
bool execute(Renderer* renderer, ANativeWindow_Buffer& buffer, MediaAsset& media, int surfaceWidth, int surfaceHeight) override {
|
||||
// 1. 애니메이션이 이미 끝났으면 더 이상 계산하지 않음
|
||||
if (cycleComplete_) {
|
||||
// 마지막 위치에 고정하여 그림
|
||||
renderer->drawMedia(buffer, media, 1.0f, offsetX_, offsetY_, getBaseScale(media, surfaceWidth, surfaceHeight));
|
||||
return cycleComplete_;
|
||||
}
|
||||
|
||||
// 2. Pan 모드에 필요한 overflow(화면 밖으로 넘친 영역) 계산
|
||||
float overflowX = 0.0f, overflowY = 0.0f;
|
||||
float scale = getBaseScale(media, surfaceWidth, surfaceHeight);
|
||||
float mediaW = static_cast<float>(media.getWidth());
|
||||
float mediaH = static_cast<float>(media.getHeight());
|
||||
if ((mediaW / mediaH) > ((float)surfaceWidth / surfaceHeight)) {
|
||||
overflowX = std::max(0.0f, mediaW * scale - surfaceWidth);
|
||||
} else {
|
||||
overflowY = std::max(0.0f, mediaH * scale - surfaceHeight);
|
||||
}
|
||||
|
||||
// 3. 좌표 업데이트
|
||||
bool xDone = (overflowX <= 0);
|
||||
bool yDone = (overflowY <= 0);
|
||||
|
||||
if (overflowX > 0) {
|
||||
offsetX_ += animationSpeed_ * xDirection_;
|
||||
if (xDirection_ == 1 && offsetX_ >= overflowX) { offsetX_ = overflowX; xDirection_ = -1; }
|
||||
else if (xDirection_ == -1 && offsetX_ <= 0) { offsetX_ = 0; xDirection_ = 1; xDone = true; }
|
||||
}
|
||||
if (overflowY > 0) {
|
||||
offsetY_ += animationSpeed_ * yDirection_;
|
||||
if (yDirection_ == 1 && offsetY_ >= overflowY) { offsetY_ = overflowY; yDirection_ = -1; }
|
||||
else if (yDirection_ == -1 && offsetY_ <= 0) { offsetY_ = 0; yDirection_ = 1; yDone = true; }
|
||||
}
|
||||
|
||||
// 4. X, Y축 왕복이 모두 끝났는지 확인
|
||||
if (xDone && yDone) {
|
||||
cycleComplete_ = true;
|
||||
}
|
||||
|
||||
// 5. 계산된 최종 좌표로 그림
|
||||
renderer->drawMedia(buffer, media, 1.0f, offsetX_, offsetY_, scale);
|
||||
|
||||
return cycleComplete_;
|
||||
}
|
||||
|
||||
private:
|
||||
float offsetX_, offsetY_;
|
||||
int xDirection_, yDirection_;
|
||||
bool cycleComplete_;
|
||||
|
||||
float getBaseScale(MediaAsset& media, int surfaceWidth, int surfaceHeight) {
|
||||
float scale;
|
||||
if ((static_cast<float>(media.getWidth()) / media.getHeight()) > ((float)surfaceWidth / surfaceHeight)) {
|
||||
scale = (float)surfaceHeight / media.getHeight();
|
||||
} else {
|
||||
scale = (float)surfaceWidth / media.getWidth();
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// --- PAN_ONE_WAY (편도 이동) 애니메이션 ---
|
||||
// ====================================================================
|
||||
class PanOneWayAnimation : public AnimationStrategy {
|
||||
public:
|
||||
PanOneWayAnimation(float speed) : AnimationStrategy(speed) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
offsetX_ = 0.0f;
|
||||
offsetY_ = 0.0f;
|
||||
cycleComplete_ = false;
|
||||
}
|
||||
|
||||
bool execute(Renderer* renderer, ANativeWindow_Buffer& buffer, MediaAsset& media, int surfaceWidth, int surfaceHeight) override {
|
||||
if (cycleComplete_) {
|
||||
renderer->drawMedia(buffer, media, 1.0f, offsetX_, offsetY_, getBaseScale(media, surfaceWidth, surfaceHeight));
|
||||
return cycleComplete_;
|
||||
}
|
||||
|
||||
float overflowX = 0.0f, overflowY = 0.0f;
|
||||
float scale = getBaseScale(media, surfaceWidth, surfaceHeight);
|
||||
float mediaW = static_cast<float>(media.getWidth());
|
||||
float mediaH = static_cast<float>(media.getHeight());
|
||||
if ((mediaW / mediaH) > ((float)surfaceWidth / surfaceHeight)) {
|
||||
overflowX = std::max(0.0f, mediaW * scale - surfaceWidth);
|
||||
} else {
|
||||
overflowY = std::max(0.0f, mediaH * scale - surfaceHeight);
|
||||
}
|
||||
|
||||
bool xReachedEnd = (overflowX <= 0);
|
||||
bool yReachedEnd = (overflowY <= 0);
|
||||
|
||||
if (overflowX > 0) {
|
||||
offsetX_ += animationSpeed_;
|
||||
if (offsetX_ >= overflowX) { offsetX_ = overflowX; xReachedEnd = true; }
|
||||
}
|
||||
if (overflowY > 0) {
|
||||
offsetY_ += animationSpeed_;
|
||||
if (offsetY_ >= overflowY) { offsetY_ = overflowY; yReachedEnd = true; }
|
||||
}
|
||||
|
||||
if (xReachedEnd && yReachedEnd) {
|
||||
cycleComplete_ = true;
|
||||
}
|
||||
|
||||
renderer->drawMedia(buffer, media, 1.0f, offsetX_, offsetY_, scale);
|
||||
return cycleComplete_;
|
||||
}
|
||||
|
||||
private:
|
||||
float offsetX_, offsetY_;
|
||||
bool cycleComplete_;
|
||||
|
||||
float getBaseScale(MediaAsset& media, int surfaceWidth, int surfaceHeight) {
|
||||
// (PanAnimation과 중복되지만, 각 클래스의 독립성을 위해 포함)
|
||||
float scale;
|
||||
if ((static_cast<float>(media.getWidth()) / media.getHeight()) > ((float)surfaceWidth / surfaceHeight)) {
|
||||
scale = (float)surfaceHeight / media.getHeight();
|
||||
} else {
|
||||
scale = (float)surfaceWidth / media.getWidth();
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// --- ZOOM 애니메이션 ---
|
||||
// ====================================================================
|
||||
class ZoomAnimation : public AnimationStrategy {
|
||||
public:
|
||||
ZoomAnimation(float speed) : AnimationStrategy(speed) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
scaleMultiplier_ = 1.0f;
|
||||
cycleComplete_ = false;
|
||||
zoomDirection_ = 1;
|
||||
}
|
||||
|
||||
bool execute(Renderer* renderer, ANativeWindow_Buffer& buffer, MediaAsset& media, int surfaceWidth, int surfaceHeight) override {
|
||||
if (!cycleComplete_) {
|
||||
scaleMultiplier_ += 0.0005f * animationSpeed_ * zoomDirection_;
|
||||
if (zoomDirection_ == 1 && scaleMultiplier_ >= 1.2f) { scaleMultiplier_ = 1.2f; zoomDirection_ = -1; }
|
||||
else if (zoomDirection_ == -1 && scaleMultiplier_ <= 1.0f) { scaleMultiplier_ = 1.0f; zoomDirection_ = 1; cycleComplete_ = true; }
|
||||
}
|
||||
|
||||
// ZOOM은 중앙 정렬을 기본으로 함
|
||||
float baseScale, baseOffsetX, baseOffsetY;
|
||||
renderer->calculateFitScaleAndOffset(media, surfaceWidth, surfaceHeight, baseScale, baseOffsetX, baseOffsetY);
|
||||
renderer->drawMedia(buffer, media, 1.0f, baseOffsetX, baseOffsetY, baseScale * scaleMultiplier_);
|
||||
|
||||
return cycleComplete_;
|
||||
}
|
||||
|
||||
private:
|
||||
float scaleMultiplier_;
|
||||
int zoomDirection_;
|
||||
bool cycleComplete_;
|
||||
};
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// --- PAGE_TURN (대기) 애니메이션 ---
|
||||
// ====================================================================
|
||||
class PageTurnAnimation : public AnimationStrategy {
|
||||
public:
|
||||
PageTurnAnimation(float speed, long long delay) : AnimationStrategy(speed), delayMs_(delay) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
cycleComplete_ = false;
|
||||
startTime_ = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
bool execute(Renderer* renderer, ANativeWindow_Buffer& buffer, MediaAsset& media, int surfaceWidth, int surfaceHeight) override {
|
||||
if (!cycleComplete_) {
|
||||
long long elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime_).count();
|
||||
if (elapsed >= delayMs_) {
|
||||
cycleComplete_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 대기하는 동안 중앙에 고정된 이미지를 그림
|
||||
float baseScale, baseOffsetX, baseOffsetY;
|
||||
renderer->calculateFitScaleAndOffset(media, surfaceWidth, surfaceHeight, baseScale, baseOffsetX, baseOffsetY);
|
||||
renderer->drawMedia(buffer, media, 1.0f, baseOffsetX, baseOffsetY, baseScale);
|
||||
|
||||
return cycleComplete_;
|
||||
}
|
||||
private:
|
||||
long long delayMs_;
|
||||
std::chrono::steady_clock::time_point startTime_;
|
||||
bool cycleComplete_;
|
||||
};
|
||||
|
||||
|
||||
// ====================================================================
|
||||
// --- NONE (애니메이션 없음) ---
|
||||
// ====================================================================
|
||||
class NoneAnimation : public AnimationStrategy {
|
||||
public:
|
||||
NoneAnimation(float speed) : AnimationStrategy(speed) {}
|
||||
void reset() override {} // 아무것도 안 함
|
||||
|
||||
bool execute(Renderer* renderer, ANativeWindow_Buffer& buffer, MediaAsset& media, int surfaceWidth, int surfaceHeight) override {
|
||||
// 중앙에 고정된 이미지만 그림
|
||||
float baseScale, baseOffsetX, baseOffsetY;
|
||||
renderer->calculateFitScaleAndOffset(media, surfaceWidth, surfaceHeight, baseScale, baseOffsetX, baseOffsetY);
|
||||
renderer->drawMedia(buffer, media, 1.0f, baseOffsetX, baseOffsetY, baseScale);
|
||||
|
||||
return true; // 즉시 완료
|
||||
}
|
||||
};
|
||||
@ -1,30 +1,22 @@
|
||||
//
|
||||
// Created by JIBUM HAN on 2025. 8. 28..
|
||||
//
|
||||
#pragma once
|
||||
#include <chrono>
|
||||
#include <android/native_window.h>
|
||||
#include "MediaAsset.h"
|
||||
|
||||
// 애니메이션의 현재 상태를 담을 구조체
|
||||
struct AnimationState {
|
||||
float offsetX = 0.0f;
|
||||
float offsetY = 0.0f;
|
||||
float scale = 1.0f;
|
||||
bool cycleComplete = false;
|
||||
};
|
||||
class Renderer; // 전방 선언
|
||||
|
||||
// 모든 '전문 요리사'의 기반이 될 추상 클래스
|
||||
class AnimationStrategy {
|
||||
public:
|
||||
virtual ~AnimationStrategy() = default;
|
||||
|
||||
// 매 프레임마다 호출되어 애니메이션 상태를 업데이트하고 반환
|
||||
virtual AnimationState update(float overflowX, float overflowY) = 0;
|
||||
/**
|
||||
* @brief 애니메이션 효과를 직접 렌더링 버퍼에 그립니다.
|
||||
* @return 애니메이션 한 사이클이 완료되었으면 true
|
||||
*/
|
||||
virtual bool execute(Renderer* renderer, ANativeWindow_Buffer& buffer, MediaAsset& media, int surfaceWidth, int surfaceHeight) = 0;
|
||||
|
||||
// 애니메이션 상태를 처음으로 리셋
|
||||
virtual void reset() = 0;
|
||||
|
||||
protected:
|
||||
// 생성자에서 애니메이션 속도를 받아 저장
|
||||
AnimationStrategy(float speed) : animationSpeed_(speed) {}
|
||||
float animationSpeed_;
|
||||
};
|
||||
@ -1,17 +0,0 @@
|
||||
//
|
||||
// Created by JIBUM HAN on 2025. 8. 28..
|
||||
//
|
||||
#include "AnimationStrategy.h"
|
||||
#include <algorithm> // for std::max
|
||||
|
||||
#ifndef LUNARLAUNCHER_NONEANIMATION_H
|
||||
#define LUNARLAUNCHER_NONEANIMATION_H
|
||||
class NoneAnimation : public AnimationStrategy {
|
||||
public:
|
||||
NoneAnimation(float speed) : AnimationStrategy(speed) { reset(); }
|
||||
void reset() override { state_.cycleComplete = true; }
|
||||
AnimationState update(float, float) override { return state_; }
|
||||
private:
|
||||
AnimationState state_;
|
||||
};
|
||||
#endif //LUNARLAUNCHER_NONEANIMATION_H
|
||||
@ -1,35 +0,0 @@
|
||||
//
|
||||
// Created by JIBUM HAN on 2025. 8. 28..
|
||||
//
|
||||
#include "AnimationStrategy.h"
|
||||
#include <algorithm> // for std::max
|
||||
|
||||
#ifndef LUNARLAUNCHER_PAGETURNANIMATION_H
|
||||
#define LUNARLAUNCHER_PAGETURNANIMATION_H
|
||||
|
||||
// --- PAGE_TURN (대기 후 페이드) 애니메이션 ---
|
||||
class PageTurnAnimation : public AnimationStrategy {
|
||||
public:
|
||||
PageTurnAnimation(float speed, long long delay) : AnimationStrategy(speed), delayMs_(delay) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
state_.cycleComplete = false;
|
||||
startTime_ = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
AnimationState update(float, float) override {
|
||||
if (state_.cycleComplete) return state_;
|
||||
|
||||
long long elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime_).count();
|
||||
if (elapsed >= delayMs_) {
|
||||
state_.cycleComplete = true;
|
||||
}
|
||||
return state_;
|
||||
}
|
||||
private:
|
||||
AnimationState state_;
|
||||
long long delayMs_;
|
||||
std::chrono::steady_clock::time_point startTime_;
|
||||
};
|
||||
|
||||
#endif //LUNARLAUNCHER_PAGETURNANIMATION_H
|
||||
@ -1,48 +0,0 @@
|
||||
//
|
||||
// Created by JIBUM HAN on 2025. 8. 28..
|
||||
//
|
||||
|
||||
#ifndef LUNARLAUNCHER_PANANIMATION_H
|
||||
#define LUNARLAUNCHER_PANANIMATION_H
|
||||
#include "AnimationStrategy.h"
|
||||
#include <algorithm> // for std::max
|
||||
|
||||
// --- PAN (왕복) 애니메이션 ---
|
||||
class PanAnimation : public AnimationStrategy {
|
||||
public:
|
||||
PanAnimation(float speed) : AnimationStrategy(speed) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
state_.offsetX = 0.0f;
|
||||
state_.offsetY = 0.0f;
|
||||
state_.cycleComplete = false;
|
||||
xDirection_ = 1;
|
||||
yDirection_ = 1;
|
||||
}
|
||||
|
||||
AnimationState update(float overflowX, float overflowY) override {
|
||||
if (state_.cycleComplete) return state_;
|
||||
|
||||
bool xDone = (overflowX <= 0);
|
||||
bool yDone = (overflowY <= 0);
|
||||
|
||||
if (overflowX > 0) {
|
||||
state_.offsetX += animationSpeed_ * xDirection_;
|
||||
if (xDirection_ == 1 && state_.offsetX >= overflowX) { state_.offsetX = overflowX; xDirection_ = -1; }
|
||||
else if (xDirection_ == -1 && state_.offsetX <= 0) { state_.offsetX = 0; xDirection_ = 1; xDone = true; }
|
||||
}
|
||||
if (overflowY > 0) {
|
||||
state_.offsetY += animationSpeed_ * yDirection_;
|
||||
if (yDirection_ == 1 && state_.offsetY >= overflowY) { state_.offsetY = overflowY; yDirection_ = -1; }
|
||||
else if (yDirection_ == -1 && state_.offsetY <= 0) { state_.offsetY = 0; yDirection_ = 1; yDone = true; }
|
||||
}
|
||||
|
||||
if (xDone && yDone) state_.cycleComplete = true;
|
||||
return state_;
|
||||
}
|
||||
|
||||
private:
|
||||
AnimationState state_;
|
||||
int xDirection_, yDirection_;
|
||||
};
|
||||
#endif //LUNARLAUNCHER_PANANIMATION_H
|
||||
@ -1,53 +0,0 @@
|
||||
//
|
||||
// Created by JIBUM HAN on 2025. 8. 28..
|
||||
//
|
||||
#include "AnimationStrategy.h"
|
||||
#include <algorithm> // for std::max
|
||||
|
||||
#ifndef LUNARLAUNCHER_PANONEWAYANIMATION_H
|
||||
#define LUNARLAUNCHER_PANONEWAYANIMATION_H
|
||||
// --- ⬇️ 새로운 PAN_ONE_WAY (편도) 애니메이션 클래스 추가 ⬇️ ---
|
||||
class PanOneWayAnimation : public AnimationStrategy {
|
||||
public:
|
||||
PanOneWayAnimation(float speed) : AnimationStrategy(speed) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
state_.offsetX = 0.0f;
|
||||
state_.offsetY = 0.0f;
|
||||
state_.cycleComplete = false;
|
||||
}
|
||||
|
||||
AnimationState update(float overflowX, float overflowY) override {
|
||||
if (state_.cycleComplete) return state_;
|
||||
|
||||
bool xReachedEnd = (overflowX <= 0);
|
||||
bool yReachedEnd = (overflowY <= 0);
|
||||
|
||||
if (overflowX > 0) {
|
||||
state_.offsetX += animationSpeed_; // 항상 정방향(+)으로만 이동
|
||||
if (state_.offsetX >= overflowX) {
|
||||
state_.offsetX = overflowX; // 끝에 도달하면 멈춤
|
||||
xReachedEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overflowY > 0) {
|
||||
state_.offsetY += animationSpeed_; // 항상 정방향(+)으로만 이동
|
||||
if (state_.offsetY >= overflowY) {
|
||||
state_.offsetY = overflowY; // 끝에 도달하면 멈춤
|
||||
yReachedEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
// X축과 Y축 이동이 모두 끝났다면 사이클 완료
|
||||
if (xReachedEnd && yReachedEnd) {
|
||||
state_.cycleComplete = true;
|
||||
}
|
||||
|
||||
return state_;
|
||||
}
|
||||
|
||||
private:
|
||||
AnimationState state_;
|
||||
};
|
||||
#endif //LUNARLAUNCHER_PANONEWAYANIMATION_H
|
||||
@ -1,10 +1,6 @@
|
||||
#include "Renderer.h"
|
||||
#include "AnimationStrategy.cpp"
|
||||
#include "TransitionStrategy.cpp"
|
||||
#include "NoneAnimation.h"
|
||||
#include "PageTurnAnimation.h"
|
||||
#include "PanAnimation.h"
|
||||
#include "PanOneWayAnimation.h"
|
||||
#include <android/log.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@ -107,62 +103,47 @@ void Renderer::determineActiveAnimationMode() {
|
||||
// ====================================================================
|
||||
|
||||
void Renderer::handleAnimationState(ANativeWindow_Buffer& buffer, int surfaceWidth, int surfaceHeight) {
|
||||
AnimationState animState;
|
||||
if (animationStrategy_) {
|
||||
float overflowX = 0.0f, overflowY = 0.0f;
|
||||
if (activeAnimationMode_ == AnimationMode::PAN || activeAnimationMode_ == AnimationMode::PAN_ONE_WAY) {
|
||||
float mediaW = static_cast<float>(currentMedia_.getWidth());
|
||||
float mediaH = static_cast<float>(currentMedia_.getHeight());
|
||||
if ((mediaW / mediaH) > (static_cast<float>(surfaceWidth) / surfaceHeight)) {
|
||||
float scale = static_cast<float>(surfaceHeight) / mediaH;
|
||||
overflowX = std::max(0.0f, mediaW * scale - surfaceWidth);
|
||||
} else {
|
||||
float scale = static_cast<float>(surfaceWidth) / mediaW;
|
||||
overflowY = std::max(0.0f, mediaH * scale - surfaceHeight);
|
||||
}
|
||||
}
|
||||
animState = animationStrategy_->update(overflowX, overflowY);
|
||||
}
|
||||
|
||||
// 안전장치: 애니메이션 전문가가 고용되지 않았다면 작업을 중단
|
||||
if (!animationStrategy_) {
|
||||
// 이 경우엔 그냥 검은 화면만 그림
|
||||
memset(buffer.bits, 0, buffer.stride * buffer.height * sizeof(uint32_t));
|
||||
float finalOffsetX, finalOffsetY, finalScale;
|
||||
if (activeAnimationMode_ == AnimationMode::PAN || activeAnimationMode_ == AnimationMode::PAN_ONE_WAY) {
|
||||
float scale;
|
||||
if ((static_cast<float>(currentMedia_.getWidth()) / currentMedia_.getHeight()) > (static_cast<float>(surfaceWidth) / surfaceHeight)) {
|
||||
scale = static_cast<float>(surfaceHeight) / currentMedia_.getHeight();
|
||||
} else {
|
||||
scale = static_cast<float>(surfaceWidth) / currentMedia_.getWidth();
|
||||
return;
|
||||
}
|
||||
finalScale = scale * animState.scale;
|
||||
finalOffsetX = animState.offsetX;
|
||||
finalOffsetY = animState.offsetY;
|
||||
} else {
|
||||
float baseScale, baseOffsetX, baseOffsetY;
|
||||
calculateFitScaleAndOffset(currentMedia_, surfaceWidth, surfaceHeight, baseScale, baseOffsetX, baseOffsetY);
|
||||
finalScale = baseScale * animState.scale;
|
||||
finalOffsetX = baseOffsetX + animState.offsetX;
|
||||
finalOffsetY = baseOffsetY + animState.offsetY;
|
||||
}
|
||||
drawMedia(buffer, currentMedia_, 1.0f, finalOffsetX, finalOffsetY, finalScale);
|
||||
|
||||
if (animState.cycleComplete && nextMedia_.isValid()) {
|
||||
// 1. 위임: 현재 애니메이션 전문가에게 모든 계산과 그리기를 맡기고, 완료 여부만 보고받음
|
||||
// (이 execute 함수 내부에서 배경을 지우고, 좌표를 계산하고, drawMedia를 호출하는 모든 작업을 수행함)
|
||||
bool isCycleComplete = animationStrategy_->execute(this, buffer, currentMedia_, surfaceWidth, surfaceHeight);
|
||||
|
||||
|
||||
// 2. 상태 전환: 애니메이션이 끝났고, 다음 미디어가 대기 중이라면 '전환' 상태로 넘어감
|
||||
if (isCycleComplete && nextMedia_.isValid()) {
|
||||
currentState_ = RenderState::TRANSITIONING;
|
||||
transitionStartTime_ = std::chrono::steady_clock::now();
|
||||
|
||||
// 사용자가 설정한 전환 모드를 확인
|
||||
TransitionMode transModeToUse = configuredTransitionMode_;
|
||||
if (transModeToUse == TransitionMode::RANDOM) {
|
||||
// RANDOM일 경우, FADE, SLIDE, MOSAIC 중에서 무작위로 선택
|
||||
std::uniform_int_distribution<int> dist(0, 2);
|
||||
transModeToUse = static_cast<TransitionMode>(dist(randomEngine_));
|
||||
int randomChoice = dist(randomEngine_);
|
||||
if (randomChoice == 0) transModeToUse = TransitionMode::FADE;
|
||||
else if (randomChoice == 1) transModeToUse = TransitionMode::SLIDE;
|
||||
else transModeToUse = TransitionMode::MOSAIC;
|
||||
}
|
||||
|
||||
// 결정된 모드에 맞는 '전환 전문가' 객체를 생성
|
||||
if (transModeToUse == TransitionMode::SLIDE) {
|
||||
transitionStrategy_ = std::make_unique<SlideTransition>(fadeDurationMs_, surfaceWidth);
|
||||
} else if (transModeToUse == TransitionMode::MOSAIC) {
|
||||
transitionStrategy_ = std::make_unique<MosaicTransition>(fadeDurationMs_, 20, 32, randomEngine_);
|
||||
} else {
|
||||
} else { // 기본값은 FADE
|
||||
transitionStrategy_ = std::make_unique<FadeTransition>(fadeDurationMs_);
|
||||
}
|
||||
|
||||
// 새로운 전환 전문가의 상태를 초기화
|
||||
if(transitionStrategy_) transitionStrategy_->reset();
|
||||
|
||||
LOGI("Animation complete. Switching to TRANSITIONING state.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +156,6 @@ void Renderer::handleTransitionState(ANativeWindow_Buffer& buffer, int surfaceWi
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
long long elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - transitionStartTime_).count();
|
||||
// 1. 상태 보고: isComplete()를 호출해서 끝났는지 "물어보기만" 함
|
||||
bool isComplete = transitionStrategy_->isComplete(elapsed);
|
||||
|
||||
transitionStrategy_->execute(this, buffer, currentMedia_, nextMedia_, elapsed);
|
||||
@ -183,6 +163,7 @@ void Renderer::handleTransitionState(ANativeWindow_Buffer& buffer, int surfaceWi
|
||||
if (isComplete) {
|
||||
currentMedia_ = std::move(nextMedia_);
|
||||
currentState_ = RenderState::ANIMATING;
|
||||
animationCycleComplete_ = false; // 새 미디어의 애니메이션 시작 준비
|
||||
determineActiveAnimationMode();
|
||||
if(animationStrategy_) animationStrategy_->reset();
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ private:
|
||||
TRANSITIONING
|
||||
};
|
||||
RenderState currentState_ = RenderState::ANIMATING;
|
||||
|
||||
bool animationCycleComplete_ = false; // <-- 이 플래그가 다시 필요
|
||||
// --- 상태별 처리를 위한 private 핸들러 함수 ---
|
||||
void handleAnimationState(ANativeWindow_Buffer& buffer, int surfaceWidth, int surfaceHeight);
|
||||
void handleTransitionState(ANativeWindow_Buffer& buffer, int surfaceWidth, int surfaceHeight);
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
//
|
||||
// Created by JIBUM HAN on 2025. 8. 28..
|
||||
//
|
||||
#include "AnimationStrategy.h"
|
||||
#include <algorithm> // for std::max
|
||||
#ifndef LUNARLAUNCHER_ZOOMANIMATION_H
|
||||
#define LUNARLAUNCHER_ZOOMANIMATION_H
|
||||
// --- ZOOM 애니메이션 ---
|
||||
class ZoomAnimation : public AnimationStrategy {
|
||||
public:
|
||||
ZoomAnimation(float speed) : AnimationStrategy(speed) { reset(); }
|
||||
|
||||
void reset() override {
|
||||
state_.scale = 1.0f;
|
||||
state_.cycleComplete = false;
|
||||
zoomDirection_ = 1;
|
||||
}
|
||||
|
||||
AnimationState update(float, float) override {
|
||||
if (state_.cycleComplete) return state_;
|
||||
|
||||
state_.scale += 0.0005f * animationSpeed_ * zoomDirection_;
|
||||
if (zoomDirection_ == 1 && state_.scale >= 1.2f) { state_.scale = 1.2f; zoomDirection_ = -1; }
|
||||
else if (zoomDirection_ == -1 && state_.scale <= 1.0f) { state_.scale = 1.0f; zoomDirection_ = 1; state_.cycleComplete = true; }
|
||||
|
||||
return state_;
|
||||
}
|
||||
|
||||
private:
|
||||
AnimationState state_;
|
||||
int zoomDirection_;
|
||||
};
|
||||
#endif //LUNARLAUNCHER_ZOOMANIMATION_H
|
||||
Loading…
x
Reference in New Issue
Block a user