mirror of
https://github.com/TomHarte/CLK.git
synced 2025-12-20 06:16:41 +00:00
Introduce animated crop.
This commit is contained in:
@@ -57,7 +57,7 @@
|
|||||||
isEnabled = "NO">
|
isEnabled = "NO">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = "--new=macintosh"
|
argument = "--new=electron"
|
||||||
isEnabled = "YES">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
|
|||||||
@@ -257,19 +257,38 @@ void CRT::advance_cycles(
|
|||||||
active_rect_.size.width < 0.95 * scan_target_modals_.output_scale.x &&
|
active_rect_.size.width < 0.95 * scan_target_modals_.output_scale.x &&
|
||||||
active_rect_.size.height < 0.95 * scan_target_modals_.output_scale.y
|
active_rect_.size.height < 0.95 * scan_target_modals_.output_scale.y
|
||||||
) {
|
) {
|
||||||
active_rect_.scale(1.05f, 1.05f);
|
active_rect_.scale(1.02f, 1.02f);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto output_frame = rect_accumulator_.posit(active_rect_);
|
const auto output_frame = rect_accumulator_.posit(active_rect_);
|
||||||
if(output_frame) {
|
if(output_frame && *output_frame != posted_rect_) {
|
||||||
scan_target_modals_.visible_area = *output_frame;
|
|
||||||
|
// Lock in any partial animation that has yet to end.
|
||||||
|
const auto animation_time = float(animation_step_) / float(AnimationSteps);
|
||||||
|
previous_posted_rect_ =
|
||||||
|
previous_posted_rect_ * (1.0f - animation_time) +
|
||||||
|
posted_rect_ * animation_time;
|
||||||
|
|
||||||
|
posted_rect_ = *output_frame;
|
||||||
|
animation_step_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(animation_step_ <= AnimationSteps) {
|
||||||
|
const auto animation_time = float(animation_step_) / float(AnimationSteps);
|
||||||
|
|
||||||
|
scan_target_modals_.visible_area =
|
||||||
|
previous_posted_rect_ * (1.0f - animation_time) +
|
||||||
|
posted_rect_ * animation_time;
|
||||||
scan_target_modals_.visible_area.origin.x /= scan_target_modals_.output_scale.x;
|
scan_target_modals_.visible_area.origin.x /= scan_target_modals_.output_scale.x;
|
||||||
scan_target_modals_.visible_area.size.width /= scan_target_modals_.output_scale.x;
|
scan_target_modals_.visible_area.size.width /= scan_target_modals_.output_scale.x;
|
||||||
scan_target_modals_.visible_area.origin.y /= scan_target_modals_.output_scale.y;
|
scan_target_modals_.visible_area.origin.y /= scan_target_modals_.output_scale.y;
|
||||||
scan_target_modals_.visible_area.size.height /= scan_target_modals_.output_scale.y;
|
scan_target_modals_.visible_area.size.height /= scan_target_modals_.output_scale.y;
|
||||||
scan_target_->set_modals(scan_target_modals_);
|
scan_target_->set_modals(scan_target_modals_);
|
||||||
|
|
||||||
|
++animation_step_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: probably something more gradated.
|
||||||
levels_are_interesting_ = level_changes_in_frame_ >= 5;
|
levels_are_interesting_ = level_changes_in_frame_ >= 5;
|
||||||
}
|
}
|
||||||
active_rect_ = Display::Rect(65536.0f, 65536.0f, 0.0f, 0.0f);
|
active_rect_ = Display::Rect(65536.0f, 65536.0f, 0.0f, 0.0f);
|
||||||
|
|||||||
@@ -370,11 +370,15 @@ private:
|
|||||||
static constexpr uint8_t DefaultAmplitude = 41;
|
static constexpr uint8_t DefaultAmplitude = 41;
|
||||||
|
|
||||||
// Accumulator for interesting detail from this frame.
|
// Accumulator for interesting detail from this frame.
|
||||||
Outputs::Display::Rect active_rect_, posted_rect_;
|
Outputs::Display::Rect active_rect_;
|
||||||
|
bool frame_is_complete_ = false;
|
||||||
|
|
||||||
|
// Current state of cropping rectangle as communicated onwards.
|
||||||
|
Outputs::Display::Rect posted_rect_, previous_posted_rect_;
|
||||||
Numeric::CubicCurve animation_curve_;
|
Numeric::CubicCurve animation_curve_;
|
||||||
|
|
||||||
int animation_step_ = 0;
|
int animation_step_ = 0;
|
||||||
static constexpr int AnimationSteps = 25;
|
static constexpr int AnimationSteps = 25;
|
||||||
bool frame_is_complete_ = false;
|
|
||||||
|
|
||||||
bool levels_are_interesting_ = false;
|
bool levels_are_interesting_ = false;
|
||||||
int level_changes_in_frame_ = 0;
|
int level_changes_in_frame_ = 0;
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ private:
|
|||||||
struct RectHistory {
|
struct RectHistory {
|
||||||
void push_back(const Display::Rect &rect) {
|
void push_back(const Display::Rect &rect) {
|
||||||
stream_[stream_pointer_] = rect;
|
stream_[stream_pointer_] = rect;
|
||||||
|
|
||||||
++stream_pointer_;
|
++stream_pointer_;
|
||||||
if(stream_pointer_ == n) stream_pointer_ = 0;
|
if(stream_pointer_ == n) stream_pointer_ = 0;
|
||||||
}
|
}
|
||||||
@@ -67,8 +66,9 @@ private:
|
|||||||
size_t stream_pointer_ = 0;
|
size_t stream_pointer_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
RectHistory<8> unions_;
|
RectHistory<32> unions_; // A long record, to try to avoid instability caused by interlaced video, flashing
|
||||||
RectHistory<8> candidates_;
|
// cursors, etc.
|
||||||
|
RectHistory<28> candidates_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,15 @@ struct Rect {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect operator +(const Rect &rhs) const {
|
||||||
|
return Rect(
|
||||||
|
origin.x + rhs.origin.x,
|
||||||
|
origin.y + rhs.origin.y,
|
||||||
|
size.width + rhs.size.width,
|
||||||
|
size.height + rhs.size.height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Rect operator /(const float multiplier) const {
|
Rect operator /(const float multiplier) const {
|
||||||
return Rect(
|
return Rect(
|
||||||
origin.x / multiplier,
|
origin.x / multiplier,
|
||||||
|
|||||||
Reference in New Issue
Block a user