Skip to content

Include gl3d scene.aspectmode changes in relayout updates #4579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/modebar/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ function handleCamera3d(gd, ev) {
var sceneId = sceneIds[i];
var camera = sceneId + '.camera';
var aspectratio = sceneId + '.aspectratio';
var aspectmode = sceneId + '.aspectmode';
var scene = fullLayout[sceneId]._scene;
var didUpdate;

Expand All @@ -365,6 +366,7 @@ function handleCamera3d(gd, ev) {
aobj[aspectratio + '.x'] = scene.viewInitial.aspectratio.x;
aobj[aspectratio + '.y'] = scene.viewInitial.aspectratio.y;
aobj[aspectratio + '.z'] = scene.viewInitial.aspectratio.z;
aobj[aspectmode] = scene.viewInitial.aspectmode;
}
}

Expand Down
14 changes: 11 additions & 3 deletions src/plots/gl3d/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ proto.tryCreatePlot = function() {
'webgl setup failed possibly due to',
isMobile ? 'disabling' : 'enabling',
'preserveDrawingBuffer config.',
'The device may not be supported by isMobile module!',
'The device may not be supported by is-mobile module!',
'Inverting preserveDrawingBuffer option in second attempt to create webgl scene.'
].join(' '));
isMobile = opts.glOptions.preserveDrawingBuffer = !opts.glOptions.preserveDrawingBuffer;
Expand Down Expand Up @@ -219,6 +219,12 @@ proto.initializeGLPlot = function() {
if(scene.isAspectChanged(layout)) {
// scene updates
update[scene.id + '.aspectratio'] = scene.glplot.getAspectratio();

if(layout[scene.id].aspectmode !== 'manual') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we get back to the original aspectmode ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When resetting the view (e.g via the modebar buttons), yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I think we have some tests related to that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it('sets aspectmode to manual when you provide any aspectratio', function(done) {
Plotly.plot(gd, [{x: [1, 2], y: [1, 2], z: [1, 2], type: 'scatter3d'}])
.then(function() {
expect(gd.layout.scene.aspectmode).toBe('auto');
return Plotly.relayout(gd, {'scene.aspectratio.x': 2});
})
.then(function() {
expect(gd.layout.scene.aspectmode).toBe('manual');
return Queue.undo(gd);
})
.then(function() {
expect(gd.layout.scene.aspectmode).toBe('auto');
})
.catch(failTest)
.then(done);
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, to be clear, once a user scrolls into a orthographic scene, the aspectmode is turned to 'manual' and the only way to get back to original aspectmode is by resetting the view?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we should keep that in viewInitial props?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is it handled currently?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apsectmode added to viewInitial in 1fdc49c and tests are added in 6ae2809.

scene.fullSceneLayout.aspectmode =
layout[scene.id].aspectmode =
update[scene.id + '.aspectmode'] = 'manual';
}
}

return update;
Expand Down Expand Up @@ -246,7 +252,6 @@ proto.initializeGLPlot = function() {
y: s * o.y,
z: s * o.z
});
scene.fullSceneLayout.aspectmode = layout[scene.id].aspectmode = 'manual';
}

relayoutCallback(scene);
Expand Down Expand Up @@ -778,14 +783,17 @@ proto.plot = function(sceneData, fullLayout, layout) {
*/
scene.glplot.setAspectratio(fullSceneLayout.aspectratio);

// save 'initial' camera view settings for modebar button
// save 'initial' aspectratio & aspectmode view settings for modebar buttons
if(!scene.viewInitial.aspectratio) {
scene.viewInitial.aspectratio = {
x: fullSceneLayout.aspectratio.x,
y: fullSceneLayout.aspectratio.y,
z: fullSceneLayout.aspectratio.z
};
}
if(!scene.viewInitial.aspectmode) {
scene.viewInitial.aspectmode = fullSceneLayout.aspectmode;
Copy link
Contributor

@etpinard etpinard Feb 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be

if(!scene.viewInitial.aspectmode) {
  scene.viewInitial.aspectmode = fullSceneLayout.aspectmode
}

that way we don't override viewInitia.aspectmodel on updates?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call.
We could. Done in c730f12.

}

// Update frame position for multi plots
var domain = fullSceneLayout.domain || null;
Expand Down
63 changes: 58 additions & 5 deletions test/jasmine/tests/gl3d_plot_interact_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -575,13 +575,19 @@ describe('Test gl3d modebar handlers - perspective case', function() {
buttonDefault.click();
});

it('@gl button resetCameraDefault3d should reset to initial aspectratios', function(done) {
it('@gl button resetCameraDefault3d should reset to initial aspectmode & aspectratios', function(done) {
var buttonDefault = selectButton(modeBar, 'resetCameraDefault3d');

expect(gd._fullLayout.scene._scene.viewInitial.aspectmode).toEqual('auto');
expect(gd._fullLayout.scene2._scene.viewInitial.aspectmode).toEqual('manual');

expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 });
expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 });

gd.once('plotly_relayout', function() {
expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('auto');
expect(gd._fullLayout.scene2._scene.fullSceneLayout.aspectmode).toBe('manual');

expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1);
Expand All @@ -595,9 +601,12 @@ describe('Test gl3d modebar handlers - perspective case', function() {
buttonDefault.click();
});

it('@gl button resetCameraLastSave3d should reset to initial aspectratios', function(done) {
it('@gl button resetCameraLastSave3d should reset to initial aspectmode & aspectratios', function(done) {
var buttonDefault = selectButton(modeBar, 'resetCameraDefault3d');

expect(gd._fullLayout.scene._scene.viewInitial.aspectmode).toEqual('auto');
expect(gd._fullLayout.scene2._scene.viewInitial.aspectmode).toEqual('manual');

expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 });
expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 });

Expand Down Expand Up @@ -771,13 +780,19 @@ describe('Test gl3d modebar handlers - orthographic case', function() {
buttonDefault.click();
});

it('@gl button resetCameraDefault3d should reset to initial aspectratios', function(done) {
it('@gl button resetCameraDefault3d should reset to initial aspectmode & aspectratios', function(done) {
var buttonDefault = selectButton(modeBar, 'resetCameraDefault3d');

expect(gd._fullLayout.scene._scene.viewInitial.aspectmode).toEqual('auto');
expect(gd._fullLayout.scene2._scene.viewInitial.aspectmode).toEqual('manual');

expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 });
expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 });

gd.once('plotly_relayout', function() {
expect(gd._fullLayout.scene._scene.aspectmode).toEqual(undefined);
expect(gd._fullLayout.scene2._scene.aspectmode).toEqual(undefined);

expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1);
Expand All @@ -791,13 +806,19 @@ describe('Test gl3d modebar handlers - orthographic case', function() {
buttonDefault.click();
});

it('@gl button resetCameraLastSave3d should reset to initial aspectratios', function(done) {
it('@gl button resetCameraLastSave3d should reset to initial aspectmode & aspectratios', function(done) {
var buttonDefault = selectButton(modeBar, 'resetCameraDefault3d');

expect(gd._fullLayout.scene._scene.viewInitial.aspectmode).toEqual('auto');
expect(gd._fullLayout.scene2._scene.viewInitial.aspectmode).toEqual('manual');

expect(gd._fullLayout.scene._scene.viewInitial.aspectratio).toEqual({ x: 1, y: 1, z: 1 });
expect(gd._fullLayout.scene2._scene.viewInitial.aspectratio).toEqual({ x: 3, y: 2, z: 1 });

gd.once('plotly_relayout', function() {
expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('auto');
expect(gd._fullLayout.scene2._scene.fullSceneLayout.aspectmode).toBe('manual');

expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1);
Expand Down Expand Up @@ -1175,7 +1196,7 @@ describe('Test gl3d drag and wheel interactions', function() {
.then(done);
});

it('@gl should update the scene aspectratio when zooming with scroll wheel i.e. orthographic case', function(done) {
it('@gl should update the scene aspectmode & aspectratio when zooming with scroll wheel i.e. orthographic case', function(done) {
var sceneLayout, sceneLayout2, sceneTarget, sceneTarget2;

var mock = {
Expand All @@ -1192,8 +1213,13 @@ describe('Test gl3d drag and wheel interactions', function() {
var aspectratio;
var relayoutEvent;
var relayoutCnt = 0;
var modeBar;

Plotly.plot(gd, mock)
.then(delay(20))
.then(function() {
modeBar = gd._fullLayout._modeBar;
})
.then(function() {
gd.on('plotly_relayout', function(e) {
relayoutCnt++;
Expand All @@ -1218,6 +1244,9 @@ describe('Test gl3d drag and wheel interactions', function() {
expect(aspectratio.x).toBeCloseTo(0.909, 3, 'aspectratio.x');
expect(aspectratio.y).toBeCloseTo(0.909, 3, 'aspectratio.y');
expect(aspectratio.z).toBeCloseTo(0.909, 3, 'aspectratio.z');

expect(relayoutEvent['scene.aspectmode']).toBe('manual');
expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('manual');
})
.then(function() {
return scroll(sceneTarget2);
Expand All @@ -1229,6 +1258,25 @@ describe('Test gl3d drag and wheel interactions', function() {
expect(aspectratio.x).toBeCloseTo(2.727, 3, 'aspectratio.x');
expect(aspectratio.y).toBeCloseTo(1.818, 3, 'aspectratio.y');
expect(aspectratio.z).toBeCloseTo(0.909, 3, 'aspectratio.z');

expect(relayoutEvent['scene2.aspectmode']).toBe('manual');
expect(gd._fullLayout.scene2._scene.fullSceneLayout.aspectmode).toBe('manual');
})
.then(function() {
var buttonDefault = selectButton(modeBar, 'resetCameraDefault3d');

buttonDefault.click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.aspectmode).toEqual(undefined);
expect(gd._fullLayout.scene2._scene.aspectmode).toEqual(undefined);

expect(gd._fullLayout.scene._scene.glplot.getAspectratio().x).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().y).toBeCloseTo(1);
expect(gd._fullLayout.scene._scene.glplot.getAspectratio().z).toBeCloseTo(1);
expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().x).toBeCloseTo(3);
expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().y).toBeCloseTo(2);
expect(gd._fullLayout.scene2._scene.glplot.getAspectratio().z).toBeCloseTo(1);
})
.catch(failTest)
.then(done);
Expand Down Expand Up @@ -1279,6 +1327,7 @@ describe('Test gl3d drag and wheel interactions', function() {
Object.keys(relayoutEvent).sort().forEach(function(key) {
expect(Object.keys(events[0])).toContain(key);
expect(key).not.toBe('scene.aspectratio');
expect(key).not.toBe('scene.aspectmode');
});
})
.catch(failTest)
Expand Down Expand Up @@ -1329,6 +1378,7 @@ describe('Test gl3d drag and wheel interactions', function() {
Object.keys(relayoutEvent).sort().forEach(function(key) {
expect(Object.keys(events[0])).toContain(key);
expect(key).not.toBe('scene.aspectratio');
expect(key).not.toBe('scene.aspectmode');
});
})
.catch(failTest)
Expand Down Expand Up @@ -1456,6 +1506,9 @@ describe('Test gl3d drag and wheel interactions', function() {
expect(aspectratio.x).toBeCloseTo(0.816, 3, 'aspectratio.x');
expect(aspectratio.y).toBeCloseTo(0.725, 3, 'aspectratio.y');
expect(aspectratio.z).toBeCloseTo(1.269, 3, 'aspectratio.z');

expect(relayoutEvent['scene.aspectmode']).toBe('manual');
expect(gd._fullLayout.scene._scene.fullSceneLayout.aspectmode).toBe('manual');
})
.then(function() {
// select a point
Expand Down