Skip to content

fix reset camera buttons to work after switching projection between perspective and orthographic #3597

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 8 commits into from
Mar 5, 2019
Merged
12 changes: 8 additions & 4 deletions src/components/modebar/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,15 +347,19 @@ function handleCamera3d(gd, ev) {
var key = sceneId + '.camera';
var scene = fullLayout[sceneId]._scene;

if(attr === 'resetDefault') {
if(attr === 'resetDefault' || attr === 'resetLastSave') {
aobj[key] = Lib.extendDeep({}, scene.cameraInitial);
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be easier to just save keys up, eye and center in scene.cameraInitial instead of saving the all scene.camera keys and then doing this fancy footwork to get the correct projection.type?

In other words, do we really need a cameraInitial stash? Could we instead just use a "view" stash:

scene.viewInitial = {
  up: {x: /**/, y: /**/, z: /**/},
  eye: {x: /**/, y: /**/, z: /**/},
  center: {x: /**/, y: /**/, z: /**/}
}

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.
Done in 9e1aa7a.


aobj[key].projection = {
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't need this after 9e1aa7a

Copy link
Contributor

@etpinard etpinard Mar 4, 2019

Choose a reason for hiding this comment

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

Actually, you'll need to tweak aobj / key logic. In the end, aobj should look like:

aobj = {
  'scene.camera.up': {/**/},
  'scene.camera.eye': {/**/},
  'scene.camera.center': {/**/}
}

as opposed to

aobj = {
  'scene.camera': {
    up: {/**/},
    eye: {/**/},
    center: {/**/}
  }
}

type: (scene.camera._ortho) ? 'orthographic' : 'perspective'
};
}

if(attr === 'resetDefault') {
aobj[key].up = null;
aobj[key].eye = null;
aobj[key].center = null;
}
else if(attr === 'resetLastSave') {
aobj[key] = Lib.extendDeep({}, scene.cameraInitial);
}
}

Registry.call('_guiRelayout', gd, aobj);
Expand Down
4 changes: 2 additions & 2 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -1589,7 +1589,7 @@ function _restyle(gd, aobj, traces) {
// and figure out what kind of graphics update we need to do
for(var ai in aobj) {
if(helpers.hasParent(aobj, ai)) {
throw new Error('cannot set ' + ai + 'and a parent attribute simultaneously');
throw new Error('cannot set ' + ai + ' and a parent attribute simultaneously');
}

var vi = aobj[ai];
Expand Down Expand Up @@ -2095,7 +2095,7 @@ function _relayout(gd, aobj) {
// alter gd.layout
for(var ai in aobj) {
if(helpers.hasParent(aobj, ai)) {
throw new Error('cannot set ' + ai + 'and a parent attribute simultaneously');
throw new Error('cannot set ' + ai + ' and a parent attribute simultaneously');
}

var p = layoutNP(layout, ai);
Expand Down
97 changes: 97 additions & 0 deletions test/jasmine/tests/gl3d_plot_interact_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,103 @@ describe('Test gl3d relayout calls', function() {
.catch(failTest)
.then(done);
});

it('@gl should maintain projection type when resetCamera buttons clicked after switching projection type from perspective to orthographic', function(done) {
Plotly.plot(gd, {
data: [{
type: 'surface',
x: [0, 1],
y: [0, 1],
z: [[0, 1], [1, 0]]
}],
layout: {
width: 300,
height: 200,
scene: {
camera: {
eye: {
x: 2,
y: 1,
z: 0.5
}
}
}
}
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.then(function() {
return Plotly.relayout(gd, 'scene.camera.projection.type', 'orthographic');
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.catch(failTest)
.then(done);
});

it('@gl should maintain projection type when resetCamera buttons clicked after switching projection type from orthographic to perspective', function(done) {
Plotly.plot(gd, {
data: [{
type: 'surface',
x: [0, 1],
y: [0, 1],
z: [[0, 1], [1, 0]]
}],
layout: {
width: 300,
height: 200,
scene: {
camera: {
eye: {
x: 2,
y: 1,
z: 0.5
},
projection: {
type: 'orthographic'
}
}
}
}
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(true, 'orthographic');
})
.then(function() {
return Plotly.relayout(gd, 'scene.camera.projection.type', 'perspective');
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraLastSave3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.then(function() {
return selectButton(gd._fullLayout._modeBar, 'resetCameraDefault3d').click();
})
.then(function() {
expect(gd._fullLayout.scene._scene.camera._ortho).toEqual(false, 'perspective');
})
.catch(failTest)
.then(done);
});
});

describe('Test gl3d annotations', function() {
Expand Down