Skip to content

Commit 8360c01

Browse files
Canvas3D: animate all the things
1 parent 5559e16 commit 8360c01

File tree

4 files changed

+167
-56
lines changed

4 files changed

+167
-56
lines changed

Diff for: src/canvas3d/canvas3d.cpp

+140-35
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,21 @@ Canvas3D::Canvas3D() : i_model_loading(0), stop_model_load_thread(false)
6262
});
6363

6464
set_can_focus(true);
65+
animators.push_back(&azimuth_animator);
66+
animators.push_back(&elevation_animator);
67+
animators.push_back(&zoom_animator);
68+
animators.push_back(&cx_animator);
69+
animators.push_back(&cy_animator);
6570
}
6671

72+
void Canvas3D::set_msd_params(const MSD::Params &params)
73+
{
74+
for (auto anim : animators) {
75+
anim->set_params(params);
76+
}
77+
}
78+
79+
6780
glm::vec2 Canvas3D::get_center_shift(const glm::vec2 &shift) const
6881
{
6982
return glm::rotate(glm::mat2(1, 0, 0, sin(glm::radians(cam_elevation))) * shift * 0.1218f * cam_distance / 105.f,
@@ -83,7 +96,8 @@ void Canvas3D::on_size_allocate(Gtk::Allocation &alloc)
8396
height = alloc.get_height();
8497
needs_resize = true;
8598
if (needs_view_all) {
86-
view_all();
99+
Canvas3DBase::view_all(); // don't use animation
100+
queue_draw();
87101
needs_view_all = false;
88102
}
89103

@@ -192,36 +206,13 @@ void Canvas3D::rotate_gesture_update_cb(GdkEventSequence *seq)
192206
auto delta = gesture_rotate->get_angle_delta();
193207
if (cam_elevation < 0)
194208
delta *= -1;
195-
cam_azimuth = gesture_rotate_cam_azimuth_orig + glm::degrees(delta);
196-
inc_cam_azimuth(0);
209+
set_cam_azimuth(gesture_rotate_cam_azimuth_orig + glm::degrees(delta));
197210
double cx, cy;
198211
gesture_rotate->get_bounding_box_center(cx, cy);
199212
auto dy = cy - gesture_rotate_pos_orig.y;
200213
set_cam_elevation(gesture_rotate_cam_elevation_orig + (dy / height) * 180);
201214
}
202215

203-
int Canvas3D::zoom_animate_step(GdkFrameClock *frame_clock)
204-
{
205-
const auto r = zoom_animator.step(gdk_frame_clock_get_frame_time(frame_clock) / 1e6);
206-
207-
auto s = zoom_animator.get_s();
208-
209-
set_cam_distance(zoom_animation_cam_dist_orig * pow(1.5, s));
210-
211-
if (!r) // should stop
212-
return G_SOURCE_REMOVE;
213-
else
214-
return G_SOURCE_CONTINUE;
215-
}
216-
217-
int Canvas3D::zoom_tick_cb(GtkWidget *cwidget, GdkFrameClock *frame_clock, gpointer user_data)
218-
{
219-
Gtk::Widget *widget = Glib::wrap(cwidget);
220-
auto canvas = dynamic_cast<Canvas3D *>(widget);
221-
return canvas->zoom_animate_step(frame_clock);
222-
}
223-
224-
225216
bool Canvas3D::on_scroll_event(GdkEventScroll *scroll_event)
226217
{
227218
auto *dev = gdk_event_get_source_device((GdkEvent *)scroll_event);
@@ -265,6 +256,20 @@ void Canvas3D::pan_rotate(GdkEventScroll *scroll_event)
265256
set_cam_azimuth(get_cam_azimuth() - delta.x * 9);
266257
set_cam_elevation(get_cam_elevation() - delta.y * 9);
267258
}
259+
260+
261+
static const float zoom_base = 1.5;
262+
263+
static float cam_dist_to_anim(float d)
264+
{
265+
return log(d) / log(zoom_base);
266+
}
267+
268+
static float cam_dist_from_anim(float d)
269+
{
270+
return pow(zoom_base, d);
271+
}
272+
268273
void Canvas3D::pan_zoom(GdkEventScroll *scroll_event)
269274
{
270275
float inc = 0;
@@ -286,27 +291,127 @@ void Canvas3D::pan_zoom(GdkEventScroll *scroll_event)
286291
if (smooth_zoom) {
287292
if (inc == 0)
288293
return;
289-
if (!zoom_animator.is_running()) {
290-
zoom_animator.start();
291-
zoom_animation_cam_dist_orig = cam_distance;
292-
gtk_widget_add_tick_callback(GTK_WIDGET(gobj()), &zoom_tick_cb, nullptr, nullptr);
293-
}
294+
start_anim();
294295
zoom_animator.target += inc;
295296
}
296297
else {
297-
set_cam_distance(cam_distance * pow(1.5, inc));
298+
set_cam_distance(cam_distance * pow(zoom_base, inc));
299+
}
300+
}
301+
302+
int Canvas3D::animate_step(GdkFrameClock *frame_clock)
303+
{
304+
bool stop = true;
305+
for (auto anim : animators) {
306+
if (anim->step(gdk_frame_clock_get_frame_time(frame_clock) / 1e6))
307+
stop = false;
308+
}
309+
310+
set_cam_azimuth(azimuth_animator.get_s());
311+
set_cam_elevation(elevation_animator.get_s());
312+
set_cam_distance(cam_dist_from_anim(zoom_animator.get_s()));
313+
set_center({cx_animator.get_s(), cy_animator.get_s()});
314+
315+
if (stop)
316+
return G_SOURCE_REMOVE;
317+
else
318+
return G_SOURCE_CONTINUE;
319+
}
320+
321+
int Canvas3D::anim_tick_cb(GtkWidget *cwidget, GdkFrameClock *frame_clock, gpointer user_data)
322+
{
323+
Gtk::Widget *widget = Glib::wrap(cwidget);
324+
auto canvas = dynamic_cast<Canvas3D *>(widget);
325+
return canvas->animate_step(frame_clock);
326+
}
327+
328+
329+
void Canvas3D::start_anim()
330+
{
331+
const bool was_stopped = !std::any_of(animators.begin(), animators.end(), [](auto x) { return x->is_running(); });
332+
333+
if (!azimuth_animator.is_running())
334+
azimuth_animator.start(cam_azimuth);
335+
336+
if (!elevation_animator.is_running())
337+
elevation_animator.start(cam_elevation);
338+
339+
if (!zoom_animator.is_running())
340+
zoom_animator.start(cam_dist_to_anim(cam_distance));
341+
342+
if (!cx_animator.is_running())
343+
cx_animator.start(center.x);
344+
345+
if (!cy_animator.is_running())
346+
cy_animator.start(center.y);
347+
348+
if (was_stopped)
349+
gtk_widget_add_tick_callback(GTK_WIDGET(gobj()), &Canvas3D::anim_tick_cb, nullptr, nullptr);
350+
}
351+
352+
void Canvas3D::animate_to_azimuth_elevation_abs(float az, float el)
353+
{
354+
if (!smooth_zoom) {
355+
set_cam_azimuth(az);
356+
set_cam_elevation(el);
357+
return;
298358
}
359+
start_anim();
360+
361+
azimuth_animator.target = az;
362+
elevation_animator.target = el;
363+
}
364+
365+
void Canvas3D::animate_to_azimuth_elevation_rel(float az, float el)
366+
{
367+
if (!smooth_zoom) {
368+
set_cam_azimuth(get_cam_azimuth() + az);
369+
set_cam_elevation(get_cam_elevation() + el);
370+
return;
371+
}
372+
start_anim();
373+
374+
azimuth_animator.target += az;
375+
elevation_animator.target += el;
299376
}
300377

301-
void Canvas3D::inc_cam_azimuth(float v)
378+
void Canvas3D::animate_zoom_step(int inc)
302379
{
303-
set_cam_azimuth(get_cam_azimuth() + v);
380+
if (!smooth_zoom) {
381+
set_cam_distance(get_cam_distance() * pow(zoom_base, inc));
382+
return;
383+
}
384+
start_anim();
385+
386+
zoom_animator.target += inc;
387+
}
388+
389+
void Canvas3D::animate_center_rel(const glm::vec2 &d)
390+
{
391+
if (!smooth_zoom) {
392+
set_center(get_center() + d);
393+
return;
394+
}
395+
start_anim();
396+
cx_animator.target += d.x;
397+
cy_animator.target += d.y;
304398
}
305399

306400
void Canvas3D::view_all()
307401
{
308-
Canvas3DBase::view_all();
309-
queue_draw();
402+
if (!smooth_zoom) {
403+
Canvas3DBase::view_all();
404+
queue_draw();
405+
return;
406+
}
407+
if (const auto p = get_view_all_params()) {
408+
start_anim();
409+
azimuth_animator.target = p->cam_azimuth;
410+
elevation_animator.target = p->cam_elevation;
411+
zoom_animator.target = cam_dist_to_anim(p->cam_distance);
412+
cx_animator.target = p->cx;
413+
cy_animator.target = p->cy;
414+
}
310415
}
311416

312417
void Canvas3D::request_push()

Diff for: src/canvas3d/canvas3d.hpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ class Canvas3D : public Gtk::GLArea, public Canvas3DBase {
3232
void update_packages();
3333
void set_highlights(const std::set<UUID> &pkgs);
3434

35-
void inc_cam_azimuth(float v);
35+
void animate_to_azimuth_elevation_abs(float az, float el);
36+
void animate_to_azimuth_elevation_rel(float az, float el);
37+
void animate_zoom_step(int inc);
38+
void animate_center_rel(const glm::vec2 &d);
3639
void set_appearance(const Appearance &a);
3740

3841
void set_msaa(unsigned int samples);
@@ -41,6 +44,8 @@ class Canvas3D : public Gtk::GLArea, public Canvas3DBase {
4144

4245
void view_all();
4346

47+
void set_msd_params(const MSD::Params &params);
48+
4449
glm::vec2 get_center_shift(const glm::vec2 &shift) const;
4550

4651
typedef sigc::signal<void, unsigned int, unsigned int> type_signal_models_loading;
@@ -107,14 +112,19 @@ class Canvas3D : public Gtk::GLArea, public Canvas3DBase {
107112
enum class PanMode { NONE, MOVE, ROTATE };
108113
PanMode pan_mode = PanMode::NONE;
109114

110-
MSDAnimator zoom_animator;
111-
float zoom_animation_cam_dist_orig = 1;
112-
113-
static int zoom_tick_cb(GtkWidget *cwidget, GdkFrameClock *frame_clock, gpointer user_data);
114-
int zoom_animate_step(GdkFrameClock *frame_clock);
115115

116116
bool needs_resize = false;
117117

118+
MSDAnimator azimuth_animator;
119+
MSDAnimator elevation_animator;
120+
MSDAnimator zoom_animator;
121+
MSDAnimator cx_animator;
122+
MSDAnimator cy_animator;
123+
124+
std::vector<MSDAnimator *> animators;
125+
int animate_step(GdkFrameClock *frame_clock);
126+
static int anim_tick_cb(GtkWidget *cwidget, GdkFrameClock *frame_clock, gpointer user_data);
127+
void start_anim();
118128

119129
void prepare();
120130

Diff for: src/imp/3d/3d_view.cpp

+7-12
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,7 @@ View3DWindow::View3DWindow(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Buil
9090
b->show();
9191
float az = it.azimuth;
9292
float el = it.elevation;
93-
b->signal_clicked().connect([this, az, el] {
94-
canvas->set_cam_azimuth(az);
95-
canvas->set_cam_elevation(el);
96-
});
93+
b->signal_clicked().connect([this, az, el] { canvas->animate_to_azimuth_elevation_abs(az, el); });
9794
view_buttons_box->pack_start(*b, false, false, 0);
9895
}
9996
}
@@ -102,8 +99,8 @@ View3DWindow::View3DWindow(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Buil
10299
Gtk::Button *rotate_right_button;
103100
GET_WIDGET(rotate_left_button);
104101
GET_WIDGET(rotate_right_button);
105-
rotate_left_button->signal_clicked().connect([this] { canvas->inc_cam_azimuth(-90); });
106-
rotate_right_button->signal_clicked().connect([this] { canvas->inc_cam_azimuth(90); });
102+
rotate_left_button->signal_clicked().connect([this] { canvas->animate_to_azimuth_elevation_rel(-90, 0); });
103+
rotate_right_button->signal_clicked().connect([this] { canvas->animate_to_azimuth_elevation_rel(+90, 0); });
107104

108105
Gtk::Button *view_all_button;
109106
GET_WIDGET(view_all_button);
@@ -583,9 +580,8 @@ void View3DWindow::handle_pan_action(const ActionConnection &c)
583580
return;
584581
}
585582
d = d * 50;
586-
auto center = canvas->get_center();
587583
auto shift = canvas->get_center_shift({d.x, d.y});
588-
canvas->set_center(center + shift);
584+
canvas->animate_center_rel(shift);
589585
}
590586

591587
void View3DWindow::handle_zoom_action(const ActionConnection &conn)
@@ -594,23 +590,22 @@ void View3DWindow::handle_zoom_action(const ActionConnection &conn)
594590
if (conn.id.action == ActionID::ZOOM_IN)
595591
inc = -1;
596592

597-
canvas->set_cam_distance(canvas->get_cam_distance() * pow(1.5, inc));
593+
canvas->animate_zoom_step(inc);
598594
}
599595

600596
void View3DWindow::handle_rotate_action(const ActionConnection &conn)
601597
{
602598
auto inc = 90;
603599
if (conn.id.action == ActionID::ROTATE_VIEW_LEFT)
604600
inc = -90;
605-
canvas->inc_cam_azimuth(inc);
601+
canvas->animate_to_azimuth_elevation_rel(inc, 0);
606602
}
607603

608604
void View3DWindow::handle_view_action(const ActionConnection &conn)
609605
{
610606
for (const auto &it : views) {
611607
if (it.action == conn.id.action) {
612-
canvas->set_cam_azimuth(it.azimuth);
613-
canvas->set_cam_elevation(it.elevation);
608+
canvas->animate_to_azimuth_elevation_abs(it.azimuth, it.elevation);
614609
return;
615610
}
616611
}

Diff for: src/pool-prj-mgr/preferences/preferences_window_misc.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,10 @@ MiscPreferencesEditor::MiscPreferencesEditor(Preferences &prefs) : preferences(p
251251
gr->add_row(*r);
252252
}
253253
{
254-
auto r = Gtk::manage(new PreferencesRowBool("Smooth zoom 3D views",
255-
"Use mass spring damper model to smooth zooming", preferences,
256-
preferences.zoom.smooth_zoom_3d));
254+
auto r = Gtk::manage(new PreferencesRowBool(
255+
"Smooth zoom 3D views",
256+
"Use mass spring damper model to smooth zooming and other transitions such as rotation",
257+
preferences, preferences.zoom.smooth_zoom_3d));
257258
gr->add_row(*r);
258259
}
259260
{

0 commit comments

Comments
 (0)