render to canvas - persist loading in case of errors

beta.r3js.org
-=yb4f310 2017-10-09 10:18:59 +02:00
parent c3475ccef7
commit 5c5ea74e14
11 changed files with 320 additions and 71 deletions

View File

@ -187,6 +187,7 @@ GameLib.Component.COMPONENT_CONTROLS_KEYBOARD = 0x39;
GameLib.Component.COMPONENT_CONTROLS_MOUSE = 0x3a; GameLib.Component.COMPONENT_CONTROLS_MOUSE = 0x3a;
GameLib.Component.COMPONENT_MESH_TEXT = 0x3b; GameLib.Component.COMPONENT_MESH_TEXT = 0x3b;
GameLib.Component.COMPONENT_FONT = 0x3c; GameLib.Component.COMPONENT_FONT = 0x3c;
GameLib.Component.COMPONENT_CANVAS = 0x3d;
/** /**
* Returns string name for component number * Returns string name for component number
@ -256,6 +257,7 @@ GameLib.Component.GetComponentName = function(number) {
case 0x3a : return 'GameLib.D3.Controls.Mouse'; case 0x3a : return 'GameLib.D3.Controls.Mouse';
case 0x3b : return 'GameLib.D3.Mesh.Text'; case 0x3b : return 'GameLib.D3.Mesh.Text';
case 0x3c : return 'GameLib.D3.Font'; case 0x3c : return 'GameLib.D3.Font';
case 0x3d : return 'GameLib.D3.Canvas';
break; break;
} }

View File

@ -0,0 +1,59 @@
/**
* Raw Canvas API object - should always correspond with the Canvas Schema
* @param id
* @param name
* @param width
* @param height
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Canvas = function(
id,
name,
width,
height,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Canvas (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(width)) {
width = 512;
}
this.width = width;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 512;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(parentEntity)){
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Canvas.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Canvas.prototype.constructor = GameLib.D3.API.Canvas;
/**
* Returns an API light from an Object light
* @param objectCanvas
* @constructor
*/
GameLib.D3.API.Canvas.FromObject = function(objectCanvas) {
return new GameLib.D3.API.Canvas(
objectCanvas.id,
objectCanvas.name,
objectCanvas.width,
objectCanvas.height,
objectCanvas.parentEntity
);
};

View File

@ -17,9 +17,6 @@ GameLib.D3.API.RenderTarget = function (
name, name,
width, width,
height, height,
minFilter,
magFilter,
format,
stencilBuffer, stencilBuffer,
texture, texture,
parentEntity parentEntity
@ -44,21 +41,6 @@ GameLib.D3.API.RenderTarget = function (
} }
this.height = height; this.height = height;
if (GameLib.Utils.UndefinedOrNull(minFilter)) {
minFilter = GameLib.D3.RenderTarget.LINEAR_FILTER;
}
this.minFilter = minFilter;
if (GameLib.Utils.UndefinedOrNull(magFilter)) {
magFilter = GameLib.D3.RenderTarget.LINEAR_FILTER;
}
this.magFilter = magFilter;
if (GameLib.Utils.UndefinedOrNull(format)) {
format = GameLib.D3.RenderTarget.RGB_FORMAT;
}
this.format = format;
if (GameLib.Utils.UndefinedOrNull(stencilBuffer)) { if (GameLib.Utils.UndefinedOrNull(stencilBuffer)) {
stencilBuffer = false; stencilBuffer = false;
} }
@ -90,9 +72,6 @@ GameLib.D3.API.RenderTarget.FromObject = function(objectComponent) {
objectComponent.name, objectComponent.name,
objectComponent.width, objectComponent.width,
objectComponent.height, objectComponent.height,
objectComponent.minFilter,
objectComponent.magFilter,
objectComponent.format,
objectComponent.stencilBuffer, objectComponent.stencilBuffer,
objectComponent.texture, objectComponent.texture,
objectComponent.parentEntity objectComponent.parentEntity

View File

@ -14,6 +14,9 @@
* @param parentEntity * @param parentEntity
* @param preserveDrawingBuffer * @param preserveDrawingBuffer
* @param clippingPlanes * @param clippingPlanes
* @param bufferScene
* @param bufferCamera
* @param renderTarget
* @constructor * @constructor
*/ */
GameLib.D3.API.Renderer = function ( GameLib.D3.API.Renderer = function (
@ -30,6 +33,9 @@ GameLib.D3.API.Renderer = function (
scenes, scenes,
viewports, viewports,
clippingPlanes, clippingPlanes,
bufferScene,
bufferCamera,
renderTarget,
parentEntity parentEntity
) { ) {
if (GameLib.Utils.UndefinedOrNull(id)) { if (GameLib.Utils.UndefinedOrNull(id)) {
@ -101,6 +107,21 @@ GameLib.D3.API.Renderer = function (
} }
this.clippingPlanes = clippingPlanes; this.clippingPlanes = clippingPlanes;
if (GameLib.Utils.UndefinedOrNull(bufferScene)) {
bufferScene = null;
}
this.bufferScene = bufferScene;
if (GameLib.Utils.UndefinedOrNull(bufferCamera)) {
bufferCamera = camera;
}
this.bufferCamera = bufferCamera;
if (GameLib.Utils.UndefinedOrNull(renderTarget)) {
renderTarget = null;
}
this.renderTarget = renderTarget;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) { if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null; parentEntity = null;
} }
@ -131,6 +152,9 @@ GameLib.D3.API.Renderer.FromObject = function(objectComponent) {
objectComponent.scenes, objectComponent.scenes,
objectComponent.viewports, objectComponent.viewports,
objectComponent.clippingPlanes, objectComponent.clippingPlanes,
objectComponent.bufferScene,
objectComponent.bufferCamera,
objectComponent.renderTarget,
objectComponent.parentEntity objectComponent.parentEntity
); );
}; };

View File

@ -21,6 +21,7 @@
* @param unpackAlignment * @param unpackAlignment
* @param premultiplyAlpha * @param premultiplyAlpha
* @param encoding * @param encoding
* @param canvas
* @param parentEntity * @param parentEntity
* @constructor * @constructor
*/ */
@ -46,6 +47,7 @@ GameLib.D3.API.Texture = function(
unpackAlignment, unpackAlignment,
premultiplyAlpha, premultiplyAlpha,
encoding, encoding,
canvas,
parentEntity parentEntity
) { ) {
if (GameLib.Utils.UndefinedOrNull(parentEntity)) { if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
@ -158,6 +160,11 @@ GameLib.D3.API.Texture = function(
} }
this.encoding = encoding; this.encoding = encoding;
if (GameLib.Utils.UndefinedOrNull(canvas)) {
canvas = null;
}
this.canvas = canvas;
this.needsUpdate = false; this.needsUpdate = false;
}; };
@ -192,6 +199,7 @@ GameLib.D3.API.Texture.FromObject = function(objectTexture) {
objectTexture.unpackAlignment, objectTexture.unpackAlignment,
objectTexture.premultiplyAlpha, objectTexture.premultiplyAlpha,
objectTexture.encoding, objectTexture.encoding,
objectTexture.canvas,
objectTexture.parentEntity objectTexture.parentEntity
) )
}; };

95
src/game-lib-d3-canvas.js Normal file
View File

@ -0,0 +1,95 @@
/**
* Canvas Superset - The apiCanvas properties get moved into the Canvas object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiCanvas GameLib.D3.API.Canvas
* @constructor
*/
GameLib.D3.Canvas = function(
graphics,
apiCanvas
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiCanvas)) {
apiCanvas = {};
}
if (apiCanvas instanceof GameLib.D3.Canvas) {
return apiCanvas;
}
GameLib.D3.API.Canvas.call(
this,
apiCanvas.id,
apiCanvas.name,
apiCanvas.width,
apiCanvas.height,
apiCanvas.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_CANVAS
);
};
GameLib.D3.Canvas.prototype = Object.create(GameLib.D3.API.Canvas.prototype);
GameLib.D3.Canvas.prototype.constructor = GameLib.D3.Canvas;
/**
* Creates a light instance
* @returns {*}
*/
GameLib.D3.Canvas.prototype.createInstance = function() {
var instance = document.createElement('canvas');
instance.width = this.width;
instance.height = this.height;
return instance;
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Canvas.prototype.updateInstance = function() {
if (GameLib.Utils.UndefinedOrNull(this.instance)) {
this.instance = document.createElement('canvas');
this.loaded = true;
}
this.instance.width = this.width;
this.instance.height = this.height;
};
/**
* Converts a GameLib.D3.Canvas to a GameLib.D3.API.Canvas
* @returns {GameLib.D3.API.Canvas}
*/
GameLib.D3.Canvas.prototype.toApiObject = function() {
return new GameLib.D3.API.Canvas(
this.id,
this.name,
this.width,
this.height,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Returns a new GameLib.D3.Canvas from a GameLib.D3.API.Canvas
* @param graphics GameLib.D3.Graphics
* @param objectCanvas GameLib.D3.API.Canvas
* @returns {GameLib.D3.Canvas}
*/
GameLib.D3.Canvas.FromObject = function(graphics, objectCanvas) {
return new GameLib.D3.Canvas(
graphics,
GameLib.D3.API.Canvas.FromObject(objectCanvas)
);
};

View File

@ -26,9 +26,6 @@ GameLib.D3.RenderTarget = function (
apiRenderTarget.name, apiRenderTarget.name,
apiRenderTarget.width, apiRenderTarget.width,
apiRenderTarget.height, apiRenderTarget.height,
apiRenderTarget.minFilter,
apiRenderTarget.magFilter,
apiRenderTarget.format,
apiRenderTarget.stencilBuffer, apiRenderTarget.stencilBuffer,
apiRenderTarget.texture apiRenderTarget.texture
); );
@ -45,35 +42,28 @@ GameLib.D3.RenderTarget = function (
GameLib.D3.RenderTarget.prototype = Object.create(GameLib.D3.API.RenderTarget.prototype); GameLib.D3.RenderTarget.prototype = Object.create(GameLib.D3.API.RenderTarget.prototype);
GameLib.D3.RenderTarget.prototype.constructor = GameLib.D3.RenderTarget; GameLib.D3.RenderTarget.prototype.constructor = GameLib.D3.RenderTarget;
/**
* Some constants (based on THREE.js constants - update if needed)
* @type {number}
*/
GameLib.D3.RenderTarget.LINEAR_FILTER = 1006;
GameLib.D3.RenderTarget.RGB_FORMAT = 1022;
GameLib.D3.RenderTarget.RGBA_FORMAT = 1023;
/** /**
* Creates a Render Target instance * Creates a Render Target instance
* @returns {*} * @returns {*}
*/ */
GameLib.D3.RenderTarget.prototype.createInstance = function() { GameLib.D3.RenderTarget.prototype.createInstance = function() {
var instance = new THREE.WebGLRenderTarget( var instance = null;
this.width,
this.height, if (this.texture && this.texture.loaded) {
{
minFilter : this.minFilter, instance = new THREE.WebGLRenderTarget(
magFilter : this.magFilter, this.width,
format : this.format, this.height,
stencilBuffer : this.stencilBuffer {
} stencilBuffer : this.stencilBuffer
); }
);
if (this.texture instanceof GameLib.D3.Texture && this.texture.instance) {
instance.texture = this.texture.instance; instance.texture = this.texture.instance;
} }
return instance; return instance;
}; };
@ -81,14 +71,25 @@ GameLib.D3.RenderTarget.prototype.createInstance = function() {
* updates instance * updates instance
*/ */
GameLib.D3.RenderTarget.prototype.updateInstance = function() { GameLib.D3.RenderTarget.prototype.updateInstance = function() {
this.instance.width = this.width;
this.instance.height = this.height; if (this.instance) {
this.instance.minFilter = this.minFilter; this.instance.setSize(this.width, this.height);
this.instance.magFilter = this.magFilter; this.instance.stencilBuffer = this.stencilBuffer;
this.instance.format = this.format; if (this.texture && this.texture.loaded) {
this.instance.stencilBuffer = this.stencilBuffer; this.instance.texture = this.texture.instance;
this.instance.texture = this.texture.instance; this.instance.texture.needsUpdate = true;
this.instance.texture.needsUpdate = true; } else {
this.instance.texture = null;
}
} else {
this.instance = this.createInstance();
if (this.instance) {
this.loaded = true;
}
}
}; };
/** /**
@ -102,9 +103,6 @@ GameLib.D3.RenderTarget.prototype.toApiObject = function() {
this.name, this.name,
this.width, this.width,
this.height, this.height,
this.minFilter,
this.magFilter,
this.format,
this.stencilBuffer, this.stencilBuffer,
GameLib.Utils.IdOrNull(this.texture), GameLib.Utils.IdOrNull(this.texture),
GameLib.Utils.IdOrNull(this.parentEntity) GameLib.Utils.IdOrNull(this.parentEntity)

View File

@ -37,6 +37,9 @@ GameLib.D3.Renderer = function (
apiRenderer.scenes, apiRenderer.scenes,
apiRenderer.viewports, apiRenderer.viewports,
apiRenderer.clippingPlanes, apiRenderer.clippingPlanes,
apiRenderer.bufferScene,
apiRenderer.bufferCamera,
apiRenderer.renderTarget,
apiRenderer.parentEntity apiRenderer.parentEntity
); );
@ -100,6 +103,27 @@ GameLib.D3.Renderer = function (
} }
}.bind(this)); }.bind(this));
if (this.bufferScene instanceof GameLib.D3.API.Scene) {
this.bufferScene = new GameLib.D3.Scene(
this.graphics,
this.bufferScene
)
}
if (this.bufferCamera instanceof GameLib.D3.API.Camera) {
this.bufferCamera = new GameLib.D3.Camera(
this.graphics,
this.bufferCamera
)
}
if (this.renderTarget instanceof GameLib.D3.API.RenderTarget) {
this.renderTarget = new GameLib.D3.RenderTarget(
this.graphics,
this.renderTarget
)
}
/** /**
* Only runtime Renderer Components have runtime statistics * Only runtime Renderer Components have runtime statistics
*/ */
@ -116,7 +140,10 @@ GameLib.D3.Renderer = function (
'camera' : GameLib.D3.Camera, 'camera' : GameLib.D3.Camera,
'scenes' : [GameLib.D3.Scene], 'scenes' : [GameLib.D3.Scene],
'viewports' : [GameLib.D3.Viewport], 'viewports' : [GameLib.D3.Viewport],
'clippingPlanes': [GameLib.D3.Mesh.Plane] 'clippingPlanes': [GameLib.D3.Mesh.Plane],
'bufferScene' : GameLib.D3.Scene,
'bufferCamera' : GameLib.D3.Camera,
'renderTarget' : GameLib.D3.RenderTarget
} }
); );
@ -239,6 +266,14 @@ GameLib.D3.Renderer.prototype.toApiObject = function() {
this.viewports.map(function(viewport){ this.viewports.map(function(viewport){
return GameLib.Utils.IdOrNull(viewport); return GameLib.Utils.IdOrNull(viewport);
}), }),
this.clippingPlanes.map(
function(clippingPlane) {
return GameLib.Utils.IdOrNull(clippingPlane);
}
),
GameLib.Utils.IdOrNull(this.bufferScene),
GameLib.Utils.IdOrNull(this.bufferCamera),
GameLib.Utils.IdOrNull(this.renderTarget),
GameLib.Utils.IdOrNull(this.parentEntity) GameLib.Utils.IdOrNull(this.parentEntity)
); );
@ -285,6 +320,24 @@ GameLib.D3.Renderer.prototype.render = function(delta) {
this.instance.clear(); this.instance.clear();
if (
this.bufferScene &&
this.bufferScene.loaded &&
this.bufferCamera &&
this.bufferCamera.loaded &&
this.renderTarget &&
this.renderTarget.loaded
) {
/**
* We have a buffer that should render to an offscreen render target
*/
this.instance.render(
this.bufferScene.instance,
this.bufferCamera.instance,
this.renderTarget.instance
);
}
this.viewports.map( this.viewports.map(
function(viewport) { function(viewport) {

View File

@ -43,6 +43,7 @@ GameLib.D3.Texture = function(
apiTexture.unpackAlignment, apiTexture.unpackAlignment,
apiTexture.premultiplyAlpha, apiTexture.premultiplyAlpha,
apiTexture.encoding, apiTexture.encoding,
apiTexture.canvas,
apiTexture.parentEntity apiTexture.parentEntity
); );
@ -65,11 +66,19 @@ GameLib.D3.Texture = function(
); );
} }
if (this.canvas instanceof GameLib.D3.API.Canvas) {
this.canvas = new GameLib.D3.Canvas(
this.graphics,
this.canvas
);
}
GameLib.Component.call( GameLib.Component.call(
this, this,
GameLib.Component.COMPONENT_TEXTURE, GameLib.Component.COMPONENT_TEXTURE,
{ {
'image' : GameLib.D3.Image 'image' : GameLib.D3.Image,
'canvas' : GameLib.D3.Canvas
} }
); );
}; };
@ -191,6 +200,8 @@ GameLib.D3.Texture.prototype.createInstance = function() {
this.image.instance this.image.instance
); );
instance.needsUpdate = true; instance.needsUpdate = true;
} else if (this.canvas && this.canvas.instance) {
instance = new THREE.Texture(this.canvas.instance);
} else { } else {
instance = new THREE.Texture(); instance = new THREE.Texture();
} }
@ -232,14 +243,20 @@ GameLib.D3.Texture.prototype.updateInstance = function() {
if (this.image && this.image.instance) { if (this.image && this.image.instance) {
if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_NORMAL) { if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_NORMAL) {
if (this.instance.image !== this.image.instance) {
this.instance = new THREE.Texture( /**
* Image overrides canvas
*/
if (this.instance.image !== this.image.instance) {
this.instance = new THREE.Texture(
this.image.instance this.image.instance
); );
this.mapping = this.instance.mapping; this.mapping = this.instance.mapping;
imageChanged = true; imageChanged = true;
} }
} else if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_CUBE) { } else if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_CUBE) {
if (this.instance.image[0] !== this.image.instance) { if (this.instance.image[0] !== this.image.instance) {
this.instance = new THREE.CubeTexture( this.instance = new THREE.CubeTexture(
@ -257,7 +274,13 @@ GameLib.D3.Texture.prototype.updateInstance = function() {
imageChanged = true; imageChanged = true;
} }
} }
} } else if (
this.canvas && this.canvas.instance
) {
if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_NORMAL) {
console.log('update canvas instance here');
}
}
this.instance.name = this.name; this.instance.name = this.name;
this.instance.flipY = this.flipY; this.instance.flipY = this.flipY;
@ -315,6 +338,7 @@ GameLib.D3.Texture.prototype.toApiObject = function() {
this.unpackAlignment, this.unpackAlignment,
this.premultiplyAlpha, this.premultiplyAlpha,
this.encoding, this.encoding,
GameLib.Utils.IdOrNull(this.canvas),
GameLib.Utils.IdOrNull(this.parentEntity) GameLib.Utils.IdOrNull(this.parentEntity)
); );

View File

@ -922,7 +922,10 @@ GameLib.System.Linking.prototype.onParentSceneChange = function(data) {
if (data.originalScene && data.originalScene.removeObject) { if (data.originalScene && data.originalScene.removeObject) {
data.originalScene.removeObject(data.object); data.originalScene.removeObject(data.object);
} }
data.newScene.addObject(data.object);
if (data.newScene) {
data.newScene.addObject(data.object);
}
} }
}; };

View File

@ -422,10 +422,10 @@ GameLib.System.Storage.prototype.loadComponent = function(apiUrl, toProcess, inc
if (clientErrorCallback) { if (clientErrorCallback) {
clientErrorCallback('Could not create a runtime component: ' + component.name); clientErrorCallback('Could not create a runtime component: ' + component.name);
} }
throw new Error('Could not create a runtime component: ' + component.name); //throw new Error('Could not create a runtime component: ' + component.name);
} }
if (parentEntity !== null) { if (parentEntity !== null && runtimeComponent) {
runtimeComponent.parentEntity = parentEntity; runtimeComponent.parentEntity = parentEntity;
} }
} }
@ -439,9 +439,11 @@ GameLib.System.Storage.prototype.loadComponent = function(apiUrl, toProcess, inc
) )
} }
loaded.push(runtimeComponent); if (runtimeComponent) {
loaded.push(runtimeComponent);
}
if (includeDependencies) { if (includeDependencies && runtimeComponent) {
/** /**
* Before we announce the creation of this component, we should get * Before we announce the creation of this component, we should get
* a list of all dependencies of this component, because once we announce * a list of all dependencies of this component, because once we announce
@ -525,16 +527,18 @@ GameLib.System.Storage.prototype.loadComponent = function(apiUrl, toProcess, inc
* The Linking system will then kick in and try to resolve all dependencies * The Linking system will then kick in and try to resolve all dependencies
*/ */
if (onComponentLoaded) { if (runtimeComponent && onComponentLoaded) {
onComponentLoaded(runtimeComponent); onComponentLoaded(runtimeComponent);
} }
GameLib.Event.Emit( if (runtimeComponent) {
GameLib.Event.COMPONENT_CREATED, GameLib.Event.Emit(
{ GameLib.Event.COMPONENT_CREATED,
component: runtimeComponent {
} component: runtimeComponent
); }
);
}
var toProcess = GameLib.Utils.Difference(loaded.map(function(component){return component.id}), loading); var toProcess = GameLib.Utils.Difference(loaded.map(function(component){return component.id}), loading);