-
Notifications
You must be signed in to change notification settings - Fork 2
/
webview.js
125 lines (97 loc) · 4.36 KB
/
webview.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
'use strict';
var createCSS3D = require('gl-css3d');
var fs = require('fs');
module.exports = function(game, opts) {
return new WebviewPlugin(game, opts);
};
module.exports.pluginInfo = {
loadAfter: ['voxel-commands', 'voxel-shader']
};
function WebviewPlugin(game, opts)
{
this.game = game;
this.shader = game.plugins.get('voxel-shader');
if (!this.shader) throw new Error('voxel-webview requires voxel-shader plugin');
this.url = opts.url || 'data:text/html,' + fs.readFileSync(__dirname + '/default.html');
opts.planeWidth = opts.planeWidth || 10;
opts.planeHeight = opts.planeHeight || 10;
//this.elementWidth = opts.elementWidth || 1024; // TODO
var iframe = document.createElement('iframe');
iframe.src = this.url;
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.id = 'voxel-webview';
//opts.tint = opts.tint || [1,0,0,0];
opts.flipX = false; // for some reason
this.css3d = createCSS3D(iframe, opts);
this.enable();
}
WebviewPlugin.prototype.enable = function() {
if (this.game.shell.gl) {
// gl is already initialized - we won't receive gl-init, or the first gl-resize
// call it here (on-demand plugin loading) TODO: cleaner generic fix for plugins receiving init events too late
this.ginit();
this.updatePerspective();
} else {
this.game.shell.on('gl-init', this.onInit = this.ginit.bind(this));
}
this.shader.on('updateProjectionMatrix', this.onUpdatePerspective = this.updatePerspective.bind(this));
this.game.shell.on('gl-render', this.onRender = this.render.bind(this));
var self = this;
window.addEventListener('click', this.onClick = function(ev) {
// click anywhere outside of iframe to exit TODO: what if it fills the entire screen? (alternate escape hatch)
// (we won't receive click events for the iframe here)
// TODO: register on WebGL canvas element instead?
// tried this.game.view.renderer.domElement but didn't receive events
if (document.getElementById('voxel-webview').parentElement.parentElement.style.zIndex === '0') {
document.getElementById('voxel-webview').parentElement.parentElement.style.zIndex = '-1';
}
});
// commands for interacting TODO: replace with something in-game (survival), https://github.com/deathcap/voxel-webview/issues/3
var commands = this.game.plugins.get('voxel-commands');
if (commands) {
commands.registerCommand('url',
this.onURL = function(address) {
if (!address || address.length === 0) {
address = window.location.origin; // load self
}
if (address.indexOf('://') === -1) {
address = 'http://' + address; // so example.com doesn't load relative path
}
document.getElementById('voxel-webview').src = address; // TODO: set url through .url setter?
},
'address',
'loads URL into webview');
commands.registerCommand('web',
this.onWeb = function() {
// bring to foreground
// TODO: alternatively could toggle pointer-events, see https://github.com/deathcap/voxel-webview/issues/1#issuecomment-74467436
// but raising the z-index unobscures the page for easier user interaction
var z = document.getElementById('voxel-webview').parentElement.parentElement.style.zIndex;
document.getElementById('voxel-webview').parentElement.parentElement.style.zIndex = {'-1':0, 0:-1}[z];
},
'',
'interact with a webview');
}
};
WebviewPlugin.prototype.disable = function() {
window.removeEventListener('click', this.onClick);
var commands = this.game.plugins.get('voxel-commands');
if (commands) {
commands.unregisterCommand('url', this.onURL);
commands.unregisterCommand('web', this.onWeb);
}
this.game.shell.removeListener('gl-render', this.onRender);
if (this.onInit) this.game.shell.removeListener('gl-init', this.onInit);
this.shader.removeListener('updateProjectionMatrix', this.onUpdatePerspective);
};
WebviewPlugin.prototype.ginit = function(gl) {
this.css3d.ginit(this.game.shell.gl);
};
WebviewPlugin.prototype.updatePerspective = function() {
var cameraFOVradians = this.shader.cameraFOV * Math.PI/180;
this.css3d.updatePerspective(cameraFOVradians, this.game.shell.width, this.game.shell.height);
};
WebviewPlugin.prototype.render = function() {
this.css3d.render(this.shader.viewMatrix, this.shader.projectionMatrix);
};