390 lines
11 KiB
JavaScript
390 lines
11 KiB
JavaScript
|
/**
|
||
|
* System takes care of updating all the entities (based on their component data)
|
||
|
* @param graphics
|
||
|
* @param apiSystem GameLib.API.System
|
||
|
* @constructor
|
||
|
*/
|
||
|
GameLib.System = function(
|
||
|
graphics,
|
||
|
apiSystem
|
||
|
) {
|
||
|
|
||
|
this.graphics = graphics;
|
||
|
this.graphics.isNotThreeThrow();
|
||
|
|
||
|
if (GameLib.Utils.UndefinedOrNull(apiSystem)) {
|
||
|
apiSystem = {};
|
||
|
}
|
||
|
|
||
|
if (apiSystem instanceof GameLib.System) {
|
||
|
return apiSystem;
|
||
|
}
|
||
|
|
||
|
GameLib.API.System.call(
|
||
|
this,
|
||
|
apiSystem.id,
|
||
|
apiSystem.name,
|
||
|
apiSystem.systemType,
|
||
|
apiSystem.entityManager,
|
||
|
apiSystem.parentEntity
|
||
|
);
|
||
|
|
||
|
if (this.entityManager instanceof GameLib.API.EntityManager) {
|
||
|
this.entityManager = new GameLib.EntityManager(
|
||
|
this.graphics,
|
||
|
this.entityManager
|
||
|
);
|
||
|
}
|
||
|
|
||
|
this.saveCallback = null;
|
||
|
this.loadCallback = null;
|
||
|
|
||
|
};
|
||
|
|
||
|
GameLib.System.prototype = Object.create(GameLib.API.System.prototype);
|
||
|
GameLib.System.prototype.constructor = GameLib.System;
|
||
|
|
||
|
GameLib.System.SYSTEM_TYPE_NONE = 0x0;
|
||
|
GameLib.System.SYSTEM_TYPE_RENDER = 0x1;
|
||
|
GameLib.System.SYSTEM_TYPE_ANIMATION = 0x2;
|
||
|
GameLib.System.SYSTEM_TYPE_INPUT = 0x4;
|
||
|
GameLib.System.SYSTEM_TYPE_STORAGE = 0x8;
|
||
|
GameLib.System.SYSTEM_TYPE_GUI = 0x10;
|
||
|
GameLib.System.SYSTEM_TYPE_ALL = 0xFFFF;
|
||
|
|
||
|
/**
|
||
|
* @callback
|
||
|
* @override
|
||
|
*/
|
||
|
GameLib.System.prototype.start = function() {
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) {
|
||
|
|
||
|
/**
|
||
|
* Hookup all editor input capabilities
|
||
|
*/
|
||
|
var entities = this.entityManager.query([GameLib.D3.Input.Editor]);
|
||
|
|
||
|
entities.map(function(entity){
|
||
|
|
||
|
var component = entity.getFirstComponent(GameLib.D3.Input.Editor);
|
||
|
|
||
|
component.mouseDown = component.onMouseDown(entity, this.entityManager).bind(component);
|
||
|
component.mouseMove = component.onMouseMove(entity).bind(component);
|
||
|
component.keyDown = component.onKeyDown(entity, this.entityManager).bind(component);
|
||
|
component.keyUp = component.onKeyUp(entity, this.entityManager).bind(component);
|
||
|
|
||
|
component.domElement.instance.addEventListener('mousedown', component.mouseDown, false);
|
||
|
component.domElement.instance.addEventListener('mousemove', component.mouseMove, false);
|
||
|
component.domElement.instance.addEventListener('keydown', component.keyDown, false);
|
||
|
component.domElement.instance.addEventListener('keyup', component.keyUp, false);
|
||
|
|
||
|
component.controls = new THREE.EditorControls(
|
||
|
component.camera.instance,
|
||
|
component.domElement.instance
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* After our mouse 'up' editor controls would have updated our camera
|
||
|
* instance, so we need to update our game-lib camera to reflect these
|
||
|
* changes - we override
|
||
|
*/
|
||
|
component.mouseUp = function(center) {
|
||
|
return function() {
|
||
|
var camera = entity.getFirstComponent(GameLib.D3.Camera);
|
||
|
camera.position.x = camera.instance.position.x;
|
||
|
camera.position.y = camera.instance.position.y;
|
||
|
camera.position.z = camera.instance.position.z;
|
||
|
|
||
|
camera.quaternion.x = camera.instance.quaternion.x;
|
||
|
camera.quaternion.y = camera.instance.quaternion.y;
|
||
|
camera.quaternion.z = camera.instance.quaternion.z;
|
||
|
camera.quaternion.w = camera.instance.quaternion.w;
|
||
|
|
||
|
camera.lookAt.x = center.x;
|
||
|
camera.lookAt.y = center.y;
|
||
|
camera.lookAt.z = center.z;
|
||
|
|
||
|
camera.lookAt.instance.copy(center);
|
||
|
};
|
||
|
}(component.controls.center).bind(component);
|
||
|
|
||
|
/**
|
||
|
* Same applies to our mouse 'scroll' event
|
||
|
*/
|
||
|
component.mouseWheel = function() {
|
||
|
return function() {
|
||
|
var camera = entity.getFirstComponent(GameLib.D3.Camera);
|
||
|
camera.position.x = camera.instance.position.x;
|
||
|
camera.position.y = camera.instance.position.y;
|
||
|
camera.position.z = camera.instance.position.z;
|
||
|
};
|
||
|
}.bind(component);
|
||
|
|
||
|
component.domElement.instance.addEventListener('mousewheel', component.mouseWheel, false);
|
||
|
component.domElement.instance.addEventListener('mouseup', component.mouseUp, false);
|
||
|
|
||
|
}.bind(this))
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) {
|
||
|
|
||
|
this.renderEntities = this.entityManager.query(
|
||
|
[
|
||
|
GameLib.D3.Viewport,
|
||
|
GameLib.D3.Scene,
|
||
|
GameLib.D3.Renderer,
|
||
|
GameLib.D3.Camera
|
||
|
]
|
||
|
);
|
||
|
|
||
|
this.renderEntities.map(
|
||
|
function(entity) {
|
||
|
var stats = entity.getFirstComponent(GameLib.D3.Stats);
|
||
|
stats.resize();
|
||
|
stats.domElement.instance.parentElement.appendChild(stats.instance.dom);
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_GUI) {
|
||
|
|
||
|
var guis = this.entityManager.queryComponents(GameLib.GUI);
|
||
|
|
||
|
guis.map(function(gui){
|
||
|
gui.domElement.instance.parentElement.appendChild(gui.instance.domElement);
|
||
|
})
|
||
|
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) {
|
||
|
// this.pathFollowingObjects = this.entityManager.query([GameLib.D3.PathFollowing]);
|
||
|
// this.followObjects = this.entityManager.query([GameLib.D3.Follow]);
|
||
|
// this.meshObjects = this.entityManager.query([GameLib.D3.Mesh]);
|
||
|
// this.lookAtObjects = this.entityManager.query([GameLib.D3.LookAt]);
|
||
|
// this.cameraObjects = this.entityManager.query([GameLib.D3.Camera]);
|
||
|
// this.lightObjects = this.entityManager.query([GameLib.D3.Light]);
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) {
|
||
|
|
||
|
this.subscribe(
|
||
|
GameLib.Event.SAVE,
|
||
|
this.save
|
||
|
);
|
||
|
|
||
|
this.subscribe(
|
||
|
GameLib.Event.LOAD,
|
||
|
this.load
|
||
|
)
|
||
|
}
|
||
|
|
||
|
|
||
|
this.update();
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @callback
|
||
|
* @override
|
||
|
*/
|
||
|
GameLib.System.prototype.update = function(deltaTime) {
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) {
|
||
|
// this.driveInputObjects.forEach(
|
||
|
// function(object) {
|
||
|
// object.update(deltaTime);
|
||
|
// }
|
||
|
// );
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) {
|
||
|
|
||
|
this.pathFollowingObjects.forEach(
|
||
|
function(object) {
|
||
|
object.update(deltaTime);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
this.followObjects.forEach(
|
||
|
function(object) {
|
||
|
object.update(deltaTime);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
this.lookAtObjects.forEach(
|
||
|
function(object) {
|
||
|
object.update(deltaTime);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
this.meshObjects.forEach(
|
||
|
function(object) {
|
||
|
object.updateInstance();
|
||
|
}
|
||
|
);
|
||
|
|
||
|
this.cameraObjects.forEach(
|
||
|
function(object) {
|
||
|
object.updateInstance();
|
||
|
}
|
||
|
);
|
||
|
|
||
|
this.lightObjects.forEach(
|
||
|
function(object) {
|
||
|
object.updateInstance();
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) {
|
||
|
|
||
|
this.renderEntities.map(
|
||
|
|
||
|
function(renderEntity) {
|
||
|
|
||
|
var stats = renderEntity.getFirstComponent(GameLib.D3.Stats);
|
||
|
stats.instance.begin();
|
||
|
|
||
|
var renderer = renderEntity.getFirstComponent(GameLib.D3.Renderer);
|
||
|
var camera = renderEntity.getFirstComponent(GameLib.D3.Camera);
|
||
|
var viewports = renderEntity.getComponents(GameLib.D3.Viewport);
|
||
|
var scenes = renderEntity.getComponents(GameLib.D3.Scene);
|
||
|
|
||
|
if (viewports.length > 1) {
|
||
|
renderer.instance.autoClear = false;
|
||
|
}
|
||
|
|
||
|
if (scenes.length > 1) {
|
||
|
renderer.instance.autoClear = false;
|
||
|
}
|
||
|
|
||
|
renderer.instance.clear();
|
||
|
|
||
|
viewports.map(
|
||
|
function(viewport){
|
||
|
|
||
|
renderer.instance.setViewport(
|
||
|
viewport.x * renderer.width,
|
||
|
viewport.y * renderer.height,
|
||
|
viewport.width * renderer.width,
|
||
|
viewport.height * renderer.height
|
||
|
);
|
||
|
|
||
|
function renderScene(scene) {
|
||
|
if (scene.activeCamera) {
|
||
|
renderer.instance.render(
|
||
|
scene.instance,
|
||
|
scene.activeCamera.instance
|
||
|
);
|
||
|
} else {
|
||
|
renderer.instance.render(
|
||
|
scene.instance,
|
||
|
camera.instance
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (viewport.scenes && viewport.scenes.length > 0) {
|
||
|
viewport.scenes.map(renderScene);
|
||
|
} else {
|
||
|
scenes.map(renderScene);
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
|
||
|
|
||
|
stats.instance.end();
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @callback
|
||
|
* @override
|
||
|
*/
|
||
|
GameLib.System.prototype.stop = function() {
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) {
|
||
|
|
||
|
/**
|
||
|
* Now remove all editor input capabilities
|
||
|
*/
|
||
|
var entities = this.entityManager.query([GameLib.D3.Input.Editor]);
|
||
|
|
||
|
entities.map(function(entity){
|
||
|
var component = entity.getFirstComponent(GameLib.D3.Input.Editor);
|
||
|
component.domElement.instance.removeEventListener('mousedown', component.mouseDown, false);
|
||
|
component.domElement.instance.removeEventListener('mousemove', component.mouseMove, false);
|
||
|
component.domElement.instance.removeEventListener('keydown', component.keyDown, false);
|
||
|
component.domElement.instance.removeEventListener('keyup', component.keyUp, false);
|
||
|
component.controls.dispose();
|
||
|
component.domElement.instance.removeEventListener('mouseup', component.mouseUp, false);
|
||
|
component.domElement.instance.removeEventListener('mousewheel', component.mouseWheel, false);
|
||
|
});
|
||
|
|
||
|
console.log('stopped all input systems');
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_GUI) {
|
||
|
console.log('stopping GUI system');
|
||
|
var guis = this.entityManager.queryComponents(GameLib.GUI);
|
||
|
|
||
|
guis.map(function(gui){
|
||
|
gui.domElement.instance.parentElement.removeChild(gui.instance.domElement);
|
||
|
})
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) {
|
||
|
|
||
|
this.renderEntities.map(
|
||
|
function(entity) {
|
||
|
var stats = entity.getFirstComponent(GameLib.D3.Stats);
|
||
|
stats.domElement.instance.parentElement.removeChild(stats.instance.dom);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
this.renderEntities = [];
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) {
|
||
|
// this.pathFollowingObjects = [];
|
||
|
// this.followObjects = [];
|
||
|
// this.meshObjects = [];
|
||
|
// this.lookAtObjects = [];
|
||
|
// this.cameraObjects = [];
|
||
|
// this.lightObjects = [];
|
||
|
}
|
||
|
|
||
|
if (this.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) {
|
||
|
|
||
|
this.unsubscribe(
|
||
|
GameLib.Event.SAVE,
|
||
|
this.save
|
||
|
);
|
||
|
|
||
|
this.unsubscribe(
|
||
|
GameLib.Event.LOAD,
|
||
|
this.load
|
||
|
)
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Converts runtime vector to API Vector
|
||
|
* @returns {GameLib.API.System}
|
||
|
*/
|
||
|
GameLib.System.prototype.toApiObject = function() {
|
||
|
|
||
|
return new GameLib.API.System(
|
||
|
this.id,
|
||
|
this.name,
|
||
|
this.systemType,
|
||
|
GameLib.Utils.IdOrNull(this.entityManager),
|
||
|
GameLib.Utils.IdOrNull(this.parentEntity)
|
||
|
);
|
||
|
};
|