start saving components

beta.r3js.org
Theunis J. Botha 2017-06-13 14:09:18 +02:00
parent 0e9a760d17
commit e06bccbb95
40 changed files with 359 additions and 174 deletions

View File

@ -25,6 +25,12 @@ GameLib.Event.IMAGE_CHANGE = 0x9;
GameLib.Event.TEXTURE_TYPE_CHANGE = 0xa;
GameLib.Event.NEW_ENTITY = 0xb;
GameLib.Event.MATERIAL_TYPE_CHANGED = 0xc;
GameLib.Event.SAVE = 0xd;
GameLib.Event.LOAD = 0xe;
GameLib.Event.LOADED = 0xf;
GameLib.Event.SAVE_SUCCESS = 0x10;
GameLib.Event.SAVE_FAILURE = 0x11;
GameLib.Event.LOGGED_IN = 0x12;
/**
* Subscribe to some events
@ -45,6 +51,31 @@ GameLib.Event.prototype.subscribe = function(
};
/**
* Unsubscribe to some events
* TODO: incomplete
* @param eventName
* @param callback
*/
GameLib.Event.prototype.unsubscribe = function(
eventName,
callback
) {
var index = -1;
if (GameLib.Event.Subscriptions.hasOwnProperty(eventName)) {
index = GameLib.Event.Subscriptions[eventName].indexOf(callback.bind(this));
}
if (index === -1) {
console.warn('could not unsubscribe from event - please implement this sometime (bind creates new function - store this pointer somewhere)');
} else {
GameLib.Event.Subscriptions[eventName].splice(index, 1);
}
};
/**
* Publish some event happened with some data
* @param eventName

View File

@ -1,40 +1,20 @@
/**
* API Component Interface - Do not construct objects of this type directly
* @param componentType
* @param linkedObjects
* @param loaded (indicates whether the linked Objects for this component has been loaded)
* @param parentEntity
* @param selected
* @constructor
*/
GameLib.API.Component = function(
componentType,
linkedObjects,
loaded,
parentEntity,
selected
parentEntity
) {
this.componentType = componentType;
if (GameLib.Utils.UndefinedOrNull(linkedObjects)) {
linkedObjects = {};
}
this.linkedObjects = linkedObjects;
if (GameLib.Utils.UndefinedOrNull(loaded)) {
loaded = false;
}
this.loaded = loaded;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.Utils.UndefinedOrNull(selected)) {
selected = false;
}
this.selected = selected;
};
GameLib.API.Component.prototype = Object.create(GameLib.Event.prototype);

View File

@ -3,40 +3,35 @@
* @constructor
* @param componentType
* @param linkedObjects
* @param loaded
* @param parentEntity
* @param selected
* @param guiProperties
*/
GameLib.Component = function(
componentType,
linkedObjects,
loaded,
parentEntity,
selected,
guiProperties
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(linkedObjects)) {
linkedObjects = {};
}
this.linkedObjects = linkedObjects;
this.linkedObjects.parentEntity = GameLib.Entity;
GameLib.API.Component.call(
this,
componentType,
linkedObjects,
loaded,
parentEntity,
selected
parentEntity
);
this.idToObject = {};
//this.parentObjects = [];
this.selected = false;
this.built = true;
this.built = false;
this.linkedObjects.parentEntity = GameLib.Entity;
this.saved = false;
this.loaded = false;
if (GameLib.Utils.UndefinedOrNull(guiProperties)) {
guiProperties = {};
}
this.guiProperties = guiProperties;
};
GameLib.Component.prototype = Object.create(GameLib.API.Component.prototype);
@ -88,11 +83,11 @@ GameLib.Component.prototype.toApiObject = function() {
GameLib.Component.prototype.buildIdToObject = function() {
if (!this.built) {
if (this.built) {
return;
}
this.built = false;
this.built = true;
this.idToObject = {};
@ -115,7 +110,7 @@ GameLib.Component.prototype.buildIdToObject = function() {
this.idToObject[this.id] = this;
this.built = true;
this.built = false;
};
/**
@ -221,6 +216,8 @@ GameLib.Component.prototype.linkObjects = function(idToObject) {
}
}
}
this.loaded = false;
};
GameLib.Component.prototype.clone = function() {
@ -232,5 +229,27 @@ GameLib.Component.prototype.clone = function() {
apiObject.name = apiObject.name + ' Clone (' + apiObject.id + ')';
//TODO - create runtime object - add to parent entity -
//var object = apiObject.
//var object = this.constructor.call(this, this.graphics, apiObject);
};
GameLib.Component.prototype.save = function() {
if (this.saved) {
return;
}
this.saved = true;
var apiObject = this.toApiObject(true);
delete apiObject.linkedObjects;
delete apiObject.idToObject;
this.publish(
GameLib.Event.SAVE,
apiObject
);
this.saved = false;
};

View File

@ -22,7 +22,6 @@ GameLib.API.DomElement = function(
this,
GameLib.Component.COMPONENT_DOM_ELEMENT,
null,
null,
parentEntity
);

View File

@ -18,9 +18,7 @@ GameLib.API.EntityManager = function(
GameLib.Component.COMPONENT_ENTITY_MANAGER,
{
'entities' : [GameLib.Entity]
// 'systems' : [GameLib.System]
},
null,
parentEntity
);

View File

@ -33,7 +33,6 @@ GameLib.API.Entity = function(
'components' : [GameLib.Component],
'activeComponent' : GameLib.Component
},
null,
parentEntity
);

View File

@ -24,7 +24,6 @@ GameLib.API.Mouse = function(
this,
GameLib.Component.COMPONENT_MOUSE,
null,
null,
parentEntity
);

View File

@ -21,7 +21,6 @@ GameLib.API.System = function (
{
'entityManager' : GameLib.EntityManager
},
null,
parentEntity
);

View File

@ -46,7 +46,6 @@ GameLib.D3.API.Camera = function(
this,
GameLib.Component.COMPONENT_CAMERA,
null,
null,
parentEntity
);

View File

@ -25,7 +25,6 @@ GameLib.D3.API.Composer = function (
'renderTarget' : GameLib.D3.RenderTarget,
'passes' : [GameLib.D3.Pass]
},
null,
parentEntity
);

View File

@ -23,7 +23,6 @@ GameLib.D3.API.CustomCode = function (
{
'args' : [GameLib.Component]
},
null,
parentEntity
);

View File

@ -28,7 +28,6 @@ GameLib.D3.API.Follow = function (
'currentComponent': GameLib.Component,
'targetComponent': GameLib.Component
},
null,
parentEntity
);

View File

@ -16,7 +16,6 @@ GameLib.D3.API.ImageFactory = function(
this,
GameLib.Component.COMPONENT_IMAGE_FACTORY,
null,
null,
parentEntity
);

View File

@ -21,7 +21,6 @@ GameLib.D3.API.Image = function(
this,
GameLib.Component.COMPONENT_IMAGE,
null,
null,
parentEntity
);

View File

@ -40,7 +40,6 @@ GameLib.D3.API.Input.Drive = function (
'wheelRL' : GameLib.D3.Mesh,
'wheelRR' : GameLib.D3.Mesh
},
null,
parentEntity
);

View File

@ -20,7 +20,6 @@ GameLib.D3.API.Input.Editor = function (
{
'camera' : GameLib.D3.Camera
},
null,
parentEntity
);

View File

@ -44,7 +44,6 @@ GameLib.D3.API.Light = function(
{
'parentScene' : GameLib.D3.Scene
},
null,
parentEntity
);

View File

@ -26,7 +26,6 @@ GameLib.D3.API.LookAt = function (
'currentComponent' : GameLib.Component,
'targetComponent' : GameLib.Component
},
null,
parentEntity
);

View File

@ -141,8 +141,7 @@ GameLib.D3.API.Material = function(
normalMap,
roughnessMap,
specularMap,
parentEntity,
selected
parentEntity
) {
GameLib.Component.call(
@ -162,9 +161,7 @@ GameLib.D3.API.Material = function(
'roughnessMap' : GameLib.D3.Texture,
'specularMap' : GameLib.D3.Texture
},
false,
parentEntity,
selected
parentEntity
);
if (GameLib.Utils.UndefinedOrNull(id)) {
@ -507,11 +504,6 @@ GameLib.D3.API.Material = function(
}
this.specularMap = specularMap;
if (GameLib.Utils.UndefinedOrNull(selected)) {
selected = false;
}
this.selected = selected;
this.needsUpdate = false;
};

View File

@ -57,7 +57,6 @@ GameLib.D3.API.Mesh = function(
'materials' : [GameLib.D3.Material],
'skeleton' : GameLib.D3.Skeleton
},
null,
parentEntity
);

View File

@ -26,7 +26,6 @@ GameLib.D3.API.Pass = function (
'camera' : GameLib.D3.Camera,
'scene' : GameLib.D3.Scene
},
null,
parentEntity
);

View File

@ -57,7 +57,6 @@ GameLib.D3.API.PathFollowing = function (
'mesh' : GameLib.D3.Mesh,
'raytraceMesh' : GameLib.D3.Mesh
},
null,
parentEntity
);

View File

@ -31,7 +31,6 @@ GameLib.D3.API.RenderTarget = function (
{
'texture' : GameLib.D3.Texture
},
null,
parentEntity
);

View File

@ -31,7 +31,6 @@ GameLib.D3.API.Renderer = function (
{
'domElement' : GameLib.DomElement
},
null,
parentEntity
);

View File

@ -41,7 +41,6 @@ GameLib.D3.API.Scene = function(
'images' : [GameLib.D3.Image],
'activeCamera' : GameLib.D3.Camera
},
false,
parentEntity
);

View File

@ -35,7 +35,6 @@ GameLib.D3.API.Skeleton = function (
{
'bones' : [GameLib.D3.Bone]
},
false,
parentEntity
);

View File

@ -16,7 +16,6 @@ GameLib.D3.API.Spline = function(
this,
GameLib.Component.COMPONENT_SPLINE,
null,
null,
parentEntity
);

View File

@ -59,7 +59,6 @@ GameLib.D3.API.Texture = function(
{
'image' : GameLib.D3.Image
},
null,
parentEntity
);

View File

@ -26,7 +26,6 @@ GameLib.D3.API.Viewport = function(
{
'scenes' : [GameLib.D3.Scene]
},
null,
parentEntity
);

View File

@ -287,7 +287,7 @@ GameLib.D3.Light.prototype.toApiObject = function() {
this.position.toApiObject(),
this.targetPosition.toApiObject(),
this.quaternion.toApiObject(),
this.rotation,
this.rotation.toApiObject(),
this.scale.toApiObject(),
this.distance,
this.decay,

View File

@ -915,66 +915,100 @@ GameLib.D3.Material.prototype.updateInstance = function() {
* Converts a GameLib.D3.Material to a GameLib.D3.API.Material
* @returns {GameLib.D3.API.Material}
*/
GameLib.D3.Material.prototype.toApiObject = function() {
GameLib.D3.Material.prototype.toApiObject = function(save) {
var apiAlphaMap = null;
if (this.alphaMap) {
apiAlphaMap = this.alphaMap.toApiObject();
if (save) {
this.alphaMap.save();
}
apiAlphaMap = this.alphaMap.id;
}
var apiAoMap = null;
if (this.aoMap) {
apiAoMap = this.aoMap.toApiObject();
if (save) {
this.aoMap.save();
}
apiAoMap = this.aoMap.id;
}
var apiBumpMap = null;
if (this.bumpMap) {
apiBumpMap = this.bumpMap.toApiObject();
if (save) {
this.bumpMap.save();
}
apiBumpMap = this.bumpMap.id;
}
var apiDiffuseMap = null;
if (this.diffuseMap) {
apiDiffuseMap = this.diffuseMap.toApiObject();
if (save) {
this.diffuseMap.save();
}
apiDiffuseMap = this.diffuseMap.id;
}
var apiDisplacementMap = null;
if (this.displacementMap) {
apiDisplacementMap = this.displacementMap.toApiObject();
if (save) {
this.displacementMap.save();
}
apiDisplacementMap = this.displacementMap.id;
}
var apiEmissiveMap = null;
if (this.emissiveMap) {
apiEmissiveMap = this.emissiveMap.toApiObject();
if (save) {
this.emissiveMap.save();
}
apiEmissiveMap = this.emissiveMap.id;
}
var apiEnvironmentMap = null;
if (this.environmentMap) {
apiEnvironmentMap = this.environmentMap.toApiObject();
if (save) {
this.environmentMap.save();
}
apiEnvironmentMap = this.environmentMap.id;
}
var apiLightMap = null;
if (this.lightMap) {
apiLightMap = this.lightMap.toApiObject();
if (save) {
this.lightMap.save();
}
apiLightMap = this.lightMap.id;
}
var apiMetalnessMap = null;
if (this.metalnessMap) {
apiMetalnessMap = this.metalnessMap.toApiObject();
if (save) {
this.metalnessMap.save();
}
apiMetalnessMap = this.metalnessMap.id;
}
var apiNormalMap = null;
if (this.normalMap) {
apiNormalMap = this.normalMap.toApiObject();
this.normalMap.save();
apiNormalMap = this.normalMap.id;
}
var apiRoughnessMap = null;
if (this.roughnessMap) {
apiRoughnessMap = this.roughnessMap.toApiObject();
if (save) {
this.roughnessMap.save();
}
apiRoughnessMap = this.roughnessMap.id;
}
var apiSpecularMap = null;
if (this.specularMap) {
apiSpecularMap = this.specularMap.toApiObject();
if (save) {
this.specularMap.save();
}
apiSpecularMap = this.specularMap.id;
}
return new GameLib.D3.API.Material(

View File

@ -472,12 +472,26 @@ GameLib.D3.Mesh.prototype.updateInstance = function() {
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.prototype.toApiObject = function() {
GameLib.D3.Mesh.prototype.toApiObject = function(save) {
var apiSkeleton = null;
if (this.skeleton) {
apiSkeleton = this.skeleton.toApiObject();
if (save) {
this.skeleton.save();
}
apiSkeleton = this.skeleton.id;
}
var apiMaterials = null;
if (this.materials) {
apiMaterials = this.materials.map(
function(material) {
if (save) {
material.save();
}
return material.id;
}
)
}
return new GameLib.D3.API.Mesh(
@ -491,7 +505,7 @@ GameLib.D3.Mesh.prototype.toApiObject = function() {
),
this.faces,
this.faceVertexUvs,
this.materials.map(function(material){return material.id}),
apiMaterials,
GameLib.Utils.IdOrNull(this.parentMesh),
GameLib.Utils.IdOrNull(this.parentScene),
apiSkeleton,

View File

@ -205,29 +205,41 @@ GameLib.D3.Scene.prototype.createInstance = function() {
* Converts a GameLib.D3.Scene to a GameLib.D3.API.Scene
* @returns {GameLib.D3.API.Scene}
*/
GameLib.D3.Scene.prototype.toApiObject = function() {
GameLib.D3.Scene.prototype.toApiObject = function(save) {
var apiMeshes = this.meshes.map(
function(mesh) {
return mesh.toApiObject();
if (save) {
mesh.save();
}
return mesh.id;
}
);
var apiLights = this.lights.map(
function(light) {
return light.toApiObject();
if (save) {
light.save();
}
return light.id;
}
);
var apiTextures = this.textures.map(
function(texture) {
return texture.toApiObject();
if (save) {
texture.save();
}
return texture.id;
}
);
var apiMaterials = this.materials.map(
function(material) {
return material.toApiObject();
if (save) {
material.save();
}
return material.id;
}
);

View File

@ -25,7 +25,6 @@ GameLib.D3.Stats = function(
{
'domElement': GameLib.DomElement
},
null,
parentEntity
);

View File

@ -342,10 +342,13 @@ GameLib.D3.Texture.prototype.updateInstance = function() {
* Converts a GameLib.D3.Texture to a GameLib.D3.API.Texture
* @returns {GameLib.D3.API.Texture}
*/
GameLib.D3.Texture.prototype.toApiObject = function() {
GameLib.D3.Texture.prototype.toApiObject = function(save) {
var apiImage = null;
if (this.image) {
if (save) {
this.image.save();
}
apiImage = this.image.id
}
@ -371,7 +374,7 @@ GameLib.D3.Texture.prototype.toApiObject = function() {
this.unpackAlignment,
this.premultiplyAlpha,
this.encoding,
this.parentEntity
GameLib.Utils.IdOrNull(this.parentEntity)
)
};

View File

@ -321,7 +321,10 @@ GameLib.EntityManager.FromObjectEntityManager = function(graphics, objectEntityM
*/
GameLib.EntityManager.prototype.onParentSceneChange = function(data) {
if (data.object instanceof GameLib.D3.Mesh) {
if (
data.object instanceof GameLib.D3.Mesh ||
data.object instanceof GameLib.D3.Light
) {
/**
* We remove the helper (if any) from the old scene and add it to the new scene
@ -382,9 +385,6 @@ GameLib.EntityManager.prototype.onParentSceneChange = function(data) {
}
}
if (data.object instanceof GameLib.D3.Light) {
console.log('implement remove light here');
}
};
/**
@ -399,6 +399,19 @@ GameLib.EntityManager.prototype.onParentEntityChange = function(data) {
}
data.newEntity.addComponent(data.object);
// - ok not so cool - we may have parent entities of entities -
// - so not all children should inherit the parent entity
// data.object.buildIdToObject();
//
// for (var property in data.object.idToObject) {
// if (data.object.idToObject.hasOwnProperty(property)) {
// if (data.object.idToObject[property].hasOwnProperty('parentEntity')) {
// data.object.idToObject[property].parentEntity = data.newEntity;
// }
// }
// }
};
/**

View File

@ -269,7 +269,21 @@ GameLib.GUI.prototype.buildControl = function(folder, object, property, entityMa
// );
// } else
if (object instanceof GameLib.D3.Material && property === 'materialType') {
if (object instanceof GameLib.System && property === 'systemType') {
handles.push(
folder.add(
object,
property,
{
'animation' : GameLib.System.SYSTEM_TYPE_ANIMATION,
'gui' : GameLib.System.SYSTEM_TYPE_GUI,
'input' : GameLib.System.SYSTEM_TYPE_INPUT,
'render' : GameLib.System.SYSTEM_TYPE_RENDER,
'storage' : GameLib.System.SYSTEM_TYPE_STORAGE
}
).name(property).listen()
);
} else if (object instanceof GameLib.D3.Material && property === 'materialType') {
handles.push(
folder.add(
object,

View File

@ -36,6 +36,9 @@ GameLib.System = function(
);
}
this.saveCallback = null;
this.loadCallback = null;
};
GameLib.System.prototype = Object.create(GameLib.API.System.prototype);
@ -163,7 +166,21 @@ GameLib.System.prototype.start = function() {
// this.lightObjects = this.entityManager.query([GameLib.D3.Light]);
}
this.update();
if (this.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) {
this.subscribe(
GameLib.Event.SAVE,
this.save
);
this.subscribe(
GameLib.Event.LOAD,
this.load
)
}
this.update();
};
@ -341,6 +358,19 @@ GameLib.System.prototype.stop = function() {
// this.lightObjects = [];
}
if (this.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) {
this.unsubscribe(
GameLib.Event.SAVE,
this.save
);
this.unsubscribe(
GameLib.Event.LOAD,
this.load
)
}
};
/**
@ -357,66 +387,3 @@ GameLib.System.prototype.toApiObject = function() {
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
GameLib.System.prototype.notify = function(property, constructor, action) {
this[property] = this.entityManager.queryComponents(constructor);
/**
* For meshes, we need to notify all scene objects
*/
if (constructor === GameLib.D3.Mesh) {
}
};
GameLib.System.prototype.load = function(onLoaded) {
//
// if (this.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) {
//
// }
//
// /**
// * First check if this is a client or server side request
// */
// if (typeof XMLHttpRequest === 'undefined') {
// console.warn('implement server side loading from API here');
// return onLoaded(
// null,
// new Error('not implemented')
// );
// }
//
// var xhr = new XMLHttpRequest();
// xhr.open(
// 'GET',
// apiUrl + '/scene/load' + partialSceneObject.path + '/' + partialSceneObject.name
// );
//
// xhr.onreadystatechange = function(xhr) {
//
// return function() {
//
// if (xhr.readyState === 4) {
//
// try {
// var response = JSON.parse(xhr.responseText);
// } catch (e) {
// return onLoaded(null, new Error('Could not load scene : ' + e.message));
// }
//
// if (!response.scene || response.scene.length === 0) {
// return onLoaded(null, new Error('Could not load scene'));
// }
//
// var objectScene = response.scene[0];
//
// onLoaded(GameLib.D3.Scene.FromObjectScene(graphics, objectScene));
// }
// }
// }(xhr);
//
// xhr.send();
};

View File

@ -0,0 +1,133 @@
/**
* System takes care of updating all the entities (based on their component data)
* @param graphics
* @param apiSystem GameLib.API.System
* @param apiUrl
* @param token
* @constructor
*/
GameLib.System.Storage = function(
graphics,
apiSystem,
apiUrl,
token
) {
if (GameLib.Utils.UndefinedOrNull(apiUrl)) {
console.warn('Need an API URL for a storage system');
}
this.apiUrl = apiUrl;
GameLib.System.call(
this,
graphics,
apiSystem
);
if (GameLib.Utils.UndefinedOrNull(token)) {
token = null;
}
this.token = token;
this.subscribe(
GameLib.Event.LOGGED_IN,
function(data) {
this.token = data.token;
}
)
};
GameLib.System.Storage.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Storage.prototype.constructor = GameLib.System.Storage;
/**
* 'Saves' data to baseURL
*/
GameLib.System.Storage.prototype.save = function(data) {
if (typeof XMLHttpRequest === 'undefined') {
console.log('Implement server side save here');
return;
}
var xhr = new XMLHttpRequest();
xhr.open(
'POST',
this.apiUrl + '/component/create'
);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
try {
var response = JSON.parse(this.responseText)
} catch (error) {
GameLib.Event.Emit(
GameLib.Event.SAVE_FAILURE,
{
message: this.responseText
}
)
}
if (response.result === 'success') {
GameLib.Event.Emit(
GameLib.Event.SAVE_SUCCESS,
{
message: response.message || 'Successfully saved the component'
}
)
} else {
GameLib.Event.Emit(
GameLib.Event.SAVE_FAILURE,
{
message: response.message || 'The server responded but failed to save the component'
}
)
}
}
};
xhr.send(JSON.stringify({
component : data,
session : this.token
}));
};
/**
* 'Loads' data from baseURL
*/
GameLib.System.Storage.prototype.load = function(data) {
if (typeof XMLHttpRequest === 'undefined') {
console.log('Implement server side load here');
return;
}
var xhr = new XMLHttpRequest();
xhr.open(
'GET',
this.apiUrl + '/component/' + data.id
);
xhr.onreadystatechange = function (xhr) {
return function () {
if (xhr.readyState === 4) {
this.publish(
GameLib.Event.LOADED,
{
component: JSON.parse(xhr.responseText)
}
)
}
}
}(xhr).bind(this);
xhr.send();
};