awesomer gui system

beta.r3js.org
Theunis J. Botha 2017-06-29 15:23:50 +02:00
parent 52ae5ae597
commit 6901c08c5f
9 changed files with 307 additions and 238 deletions

View File

@ -44,6 +44,12 @@ GameLib.Event.LIGHT_INSTANCE_UPDATED = 0x1c;
GameLib.Event.DELETE_COMPONENT = 0x1d;
GameLib.Event.COMPONENT_DOWNLOAD_COMPLETE = 0x1e;
GameLib.Event.COMPONENTS_LINKED = 0x1f;
GameLib.Event.UNRESOLVED_DEPENDENCIES_UPDATE = 0x20;
GameLib.Event.REGISTER_UPDATE = 0x21;
GameLib.Event.BUILD_GUI = 0x22;
GameLib.Event.MESH_DELETED = 0x23;
GameLib.Event.MESH_SELECTED = 0x24;
GameLib.Event.MESH_DESELECTED = 0x25;
/**
* Subscribe to some events
@ -54,28 +60,7 @@ GameLib.Event.prototype.subscribe = function(
eventName,
callback
) {
var fn = callback.bind(this);
if (GameLib.Event.Subscriptions.hasOwnProperty(eventName)) {
GameLib.Event.Subscriptions[eventName].push(fn);
} else {
GameLib.Event.Subscriptions[eventName] = [];
GameLib.Event.Subscriptions[eventName].push(fn);
}
/**
* Return a handle to the caller to allow us to unsubscribe to this event
*/
return {
fn : fn,
remove : function() {
GameLib.Event.Subscriptions[eventName].splice(
GameLib.Event.Subscriptions[eventName].indexOf(fn),
1
);
}
}
return GameLib.Event.Subscribe(eventName, callback.bind(this));
};
GameLib.Event.EmitInstanceEvents = function(component) {
@ -147,39 +132,39 @@ GameLib.Event.EmitInstanceEvents = function(component) {
}
};
/**
* Stop listening for this event after the callback returns true
* @param eventName
* @param callback
* @returns {{fn, remove: remove}}
*/
GameLib.Event.prototype.subscribeOnce = function(
eventName,
callback
) {
throw new Error('implement first properly');
// var fn = callback.bind(this);
//
// if (GameLib.Event.OnceSubscriptions.hasOwnProperty(eventName)) {
// GameLib.Event.OnceSubscriptions[eventName].push(fn);
// } else {
// GameLib.Event.OnceSubscriptions[eventName] = [];
// GameLib.Event.OnceSubscriptions[eventName].push(fn);
// }
//
// /**
// * Return a handle to the caller to allow us to unsubscribe to this event
// */
// return {
// fn : fn,
// remove : function() {
// GameLib.Event.Subscriptions[eventName].splice(
// GameLib.Event.Subscriptions[eventName].indexOf(fn),
// 1
// );
// }
// }
};
// /**
// * Stop listening for this event after the callback returns true
// * @param eventName
// * @param callback
// * @returns {{fn, remove: remove}}
// */
// GameLib.Event.prototype.subscribeOnce = function(
// eventName,
// callback
// ) {
// throw new Error('implement first properly');
// // var fn = callback.bind(this);
// //
// // if (GameLib.Event.OnceSubscriptions.hasOwnProperty(eventName)) {
// // GameLib.Event.OnceSubscriptions[eventName].push(fn);
// // } else {
// // GameLib.Event.OnceSubscriptions[eventName] = [];
// // GameLib.Event.OnceSubscriptions[eventName].push(fn);
// // }
// //
// // /**
// // * Return a handle to the caller to allow us to unsubscribe to this event
// // */
// // return {
// // fn : fn,
// // remove : function() {
// // GameLib.Event.Subscriptions[eventName].splice(
// // GameLib.Event.Subscriptions[eventName].indexOf(fn),
// // 1
// // );
// // }
// // }
// };
/**
*
@ -223,3 +208,29 @@ GameLib.Event.Emit = function(eventName, data) {
return count;
};
GameLib.Event.Subscribe = function(
eventName,
fn
) {
if (GameLib.Event.Subscriptions.hasOwnProperty(eventName)) {
GameLib.Event.Subscriptions[eventName].push(fn);
} else {
GameLib.Event.Subscriptions[eventName] = [];
GameLib.Event.Subscriptions[eventName].push(fn);
}
/**
* Return a handle to the caller to allow us to unsubscribe to this event
*/
return {
fn : fn,
remove : function() {
GameLib.Event.Subscriptions[eventName].splice(
GameLib.Event.Subscriptions[eventName].indexOf(fn),
1
);
}
}
};

View File

@ -3,14 +3,10 @@
* @constructor
* @param componentType
* @param linkedObjects
* @param parentEntity
* @param traverse
*/
GameLib.Component = function(
componentType,
linkedObjects,
parentEntity,
traverse
linkedObjects
) {
if (GameLib.Utils.UndefinedOrNull(linkedObjects)) {
linkedObjects = {};
@ -21,7 +17,7 @@ GameLib.Component = function(
GameLib.API.Component.call(
this,
componentType,
parentEntity
this.parentEntity
);
this.idToObject = {};
@ -32,11 +28,6 @@ GameLib.Component = function(
this.loaded = false;
if (GameLib.Utils.UndefinedOrNull(traverse)) {
traverse = true;
}
this.traverse = traverse;
this.dependencies = this.getDependencies();
if (this.dependencies.length === 0) {
@ -46,9 +37,17 @@ GameLib.Component = function(
if (this.instance) {
this.loaded = true;
this.buildIdToObject();
GameLib.Event.EmitInstanceEvents(this);
}
}
GameLib.Event.Emit(
GameLib.Event.COMPONENT_CREATED,
{
component : this
}
);
};
GameLib.Component.prototype = Object.create(GameLib.API.Component.prototype);
@ -214,10 +213,6 @@ GameLib.Component.prototype.toApiObject = function() {
*/
GameLib.Component.prototype.buildIdToObject = function() {
if (!this.traverse) {
return;
}
if (this.built) {
return;
}

View File

@ -5,7 +5,6 @@
* @param path
* @param contentType
* @param size
* @param data
* @param parentEntity GameLib.Entity
* @constructor
*/
@ -15,7 +14,6 @@ GameLib.D3.API.Image = function(
path,
contentType,
size,
data,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
@ -56,11 +54,6 @@ GameLib.D3.API.Image = function(
}
this.size = size;
if (GameLib.Utils.UndefinedOrNull(data)) {
data = null;
}
this.data = data;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
@ -82,7 +75,6 @@ GameLib.D3.API.Image.FromObject = function(objectImage) {
objectImage.path,
objectImage.contentType,
objectImage.size,
objectImage.data,
objectImage.parentEntity
);
};

View File

@ -128,22 +128,19 @@ GameLib.D3.Input.Editor.prototype.onKeyDown = function(entity, entityManager) {
if (event.code === 'Delete') {
var meshes = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Mesh]);
var guis = GameLib.EntityManager.Instance.queryComponents([GameLib.GUI]);
var deletedMeshes = [];
meshes.map(
function(mesh) {
if (mesh.selected) {
var parentEntity = mesh.parentEntity;
deletedMeshes.push(mesh);
parentEntity.removeHelper(mesh, entity);
this.removeHelper(mesh, entity);
entity.removeComponent(mesh);
entity.buildIdToObject();
guis.map(function(gui) {
gui.removeObject(mesh);
});
var scene = mesh.parentScene;
scene.removeObject(mesh);
scene.buildIdToObject();
@ -151,11 +148,13 @@ GameLib.D3.Input.Editor.prototype.onKeyDown = function(entity, entityManager) {
}.bind(this)
);
GameLib.Event.Emit(
GameLib.Event.MESH_DELETED,
{
meshes : deletedMeshes
}
);
guis.map(function(gui) {
gui.build(entityManager);
});
}
if (event.code === 'ControlLeft') {
@ -364,8 +363,6 @@ GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity, entityManager)
return;
}
var gui = entity.getFirstComponent(GameLib.GUI);
if (mesh.selected) {
helper = new GameLib.D3.Helper(
@ -387,16 +384,24 @@ GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity, entityManager)
scene.instance.add(helper.instance);
gui.addObject(mesh);
GameLib.Event.Emit(
GameLib.Event.MESH_SELECTED,
{
mesh : mesh
}
)
} else {
gui.removeObject(mesh);
GameLib.Event.Emit(
GameLib.Event.MESH_DESELECTED,
{
mesh : mesh
}
);
this.removeHelper(mesh, entity);
}
gui.build(entityManager);
}
}
}

View File

@ -15,8 +15,7 @@ GameLib.EntityManager = function() {
GameLib.Component.COMPONENT_ENTITY_MANAGER,
{
'entities' : [GameLib.Entity]
},
null
}
);
};
@ -197,16 +196,20 @@ GameLib.EntityManager.prototype.queryComponents = function(constructors) {
constructors.map(
function(constructor) {
if (component instanceof constructor) {
if (result.indexOf(component) === -1) {
result.push(component);
}
}
}
);
} else {
if (component instanceof constructors) {
if (result.indexOf(component) === -1) {
result.push(component);
}
}
}
}
);
return result;

View File

@ -270,7 +270,9 @@ GameLib.GUI.prototype.buildControl = function(folder, object, property, entityMa
'gui' : GameLib.System.SYSTEM_TYPE_GUI,
'input' : GameLib.System.SYSTEM_TYPE_INPUT,
'render' : GameLib.System.SYSTEM_TYPE_RENDER,
'storage' : GameLib.System.SYSTEM_TYPE_STORAGE
'storage' : GameLib.System.SYSTEM_TYPE_STORAGE,
'linking' : GameLib.System.SYSTEM_TYPE_LINKING,
'physics' : GameLib.System.SYSTEM_TYPE_PHYSICS
}
).name(property).listen()
);
@ -837,7 +839,7 @@ GameLib.GUI.prototype.buildVectorControl = function(folder, object, property, di
}
};
GameLib.GUI.prototype.buildSelectControl = function(folder, object, property, entityManager, constructor, parentObject) {
GameLib.GUI.prototype.buildSelectControl = function(folder, object, property, entityManager, constructor) {
var objects = entityManager.queryComponents(constructor);
@ -892,15 +894,11 @@ GameLib.GUI.prototype.buildSelectControl = function(folder, object, property, en
object.updateInstance();
}
/**
* Properties changed - rebuild the object list in the parent
*/
console.log('parentObject.buildIdToObject();');
/**
* Properties changed - rebuild GUI
*/
gui.build(entityManager);
//gui.build(entityManager);
};
@ -1037,28 +1035,7 @@ GameLib.GUI.prototype.build = function(entityManager) {
this.instance.removeAllFolders();
var discoveredObjects = [];
var parentObject = this.objects[0];
this.objects.map(
function(object) {
if (object.idToObject) {
for (var property in object.idToObject) {
if (object.idToObject.hasOwnProperty(property)) {
if (discoveredObjects.indexOf(object.idToObject[property]) === -1) {
discoveredObjects.push(object.idToObject[property]);
}
}
}
}
}.bind(this)
);
discoveredObjects.sort(
this.objects.sort(
function(a, b) {
if (a.name > b.name) {
return 1;
@ -1071,8 +1048,32 @@ GameLib.GUI.prototype.build = function(entityManager) {
return 0;
}
);
//
// var discoveredObjects = [];
//
// var parentObject = this.objects[0];
//
// this.objects.map(
//
// function(object) {
//
// if (object.idToObject) {
// for (var property in object.idToObject) {
// if (object.idToObject.hasOwnProperty(property)) {
// if (discoveredObjects.indexOf(object.idToObject[property]) === -1) {
// discoveredObjects.push(object.idToObject[property]);
// }
// }
// }
// }
//
// }.bind(this)
// );
//
// discoveredObjects
// );
discoveredObjects.map(
this.objects.map(
function(object) {
@ -1114,7 +1115,6 @@ GameLib.GUI.prototype.build = function(entityManager) {
entityManager
)
} else if (object.linkedObjects[property] instanceof Array) {
console.log('ignored array : ' + property);
this.buildArrayManager(
folder,
object,
@ -1123,7 +1123,7 @@ GameLib.GUI.prototype.build = function(entityManager) {
entityManager
)
} else {
this.buildSelectControl(folder, object, property, entityManager, object.linkedObjects[property], parentObject);
this.buildSelectControl(folder, object, property, entityManager, object.linkedObjects[property]);
}
} else if (typeof (object[property]) === 'object') {

View File

@ -10,6 +10,19 @@ GameLib.System.GUI = function(
this,
apiSystem
);
this.guis = [];
this.buildGUISubscription = null;
this.meshDeletedSubscription = null;
this.meshSelectedSubscription = null;
this.meshDeselectedSubscription = null;
this.newEntitySubscription = null;
};
GameLib.System.GUI.prototype = Object.create(GameLib.System.prototype);
@ -17,19 +30,89 @@ GameLib.System.GUI.prototype.constructor = GameLib.System.GUI;
GameLib.System.GUI.prototype.start = function() {
var guis = GameLib.EntityManager.Instance.queryComponents(GameLib.GUI);
this.guis = GameLib.EntityManager.Instance.queryComponents(GameLib.GUI);
guis.map(function(gui){
this.guis.map(function(gui){
gui.domElement.instance.parentElement.appendChild(gui.instance.domElement);
})
});
this.buildGUISubscription = this.subscribe(
GameLib.Event.BUILD_GUI,
this.buildGUI
);
this.meshDeletedSubscription = this.subscribe(
GameLib.Event.MESH_DELETED,
this.meshDeleted
);
this.meshSelectedSubscription = this.subscribe(
GameLib.Event.MESH_SELECTED,
this.meshSelected
);
this.meshDeselectedSubscription = this.subscribe(
GameLib.Event.MESH_DESELECTED,
this.meshDeslected
);
this.newEntitySubscription = this.subscribe(
GameLib.Event.NEW_ENTITY,
this.newEntity
)
};
GameLib.System.GUI.prototype.buildGUI = function(data) {
this.guis.map(function(gui){
gui.objects = [];
if (
data.components &&
data.components.length > 0
) {
gui.objects = data.components;
}
gui.build(GameLib.EntityManager.Instance);
});
};
GameLib.System.GUI.prototype.meshDeleted = function(data) {
};
GameLib.System.GUI.prototype.meshSelected = function(data) {
};
GameLib.System.GUI.prototype.meshDeslected = function(data) {
};
GameLib.System.GUI.prototype.newEntity = function(data) {
};
GameLib.System.GUI.prototype.stop = function() {
var guis = GameLib.EntityManager.Instance.queryComponents(GameLib.GUI);
guis.map(function(gui){
this.guis.map(function(gui){
gui.domElement.instance.parentElement.removeChild(gui.instance.domElement);
})
});
this.buildGUISubscription.remove();
this.meshDeletedSubscription.remove();
this.meshSelectedSubscription.remove();
this.meshDeselectedSubscription.remove();
this.newEntitySubscription.remove();
this.guis = [];
};

View File

@ -48,6 +48,13 @@ GameLib.System.Linking.prototype.start = function() {
this.register = GameLib.EntityManager.Instance.queryComponents([GameLib.Component]);
GameLib.Event.Emit(
GameLib.Event.REGISTER_UPDATE,
{
register : this.register
}
);
this.componentCreatedSubscription = this.subscribe(
GameLib.Event.COMPONENT_CREATED,
this.componentCreated.bind(this)
@ -170,7 +177,7 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) {
if (parentComponent.instance) {
parentComponent.loaded = true;
parentComponent.buildIdToObject();
if (this.resolved.indexOf(parentComponent) === -1) {
this.resolved.push(parentComponent);
}
@ -184,6 +191,13 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) {
delete this.dependencies[component.id];
GameLib.Event.Emit(
GameLib.Event.UNRESOLVED_DEPENDENCIES_UPDATE,
{
dependencies : this.dependencies
}
);
if (GameLib.Utils.IsEmpty(this.dependencies)) {
GameLib.Event.Emit(
@ -210,6 +224,13 @@ GameLib.System.Linking.prototype.registerDependencies = function(component) {
*/
this.register.push(component);
GameLib.Event.Emit(
GameLib.Event.REGISTER_UPDATE,
{
register : this.register
}
);
/**
* We only care about components with unloaded dependencies -
* other components will have already had their instance objects created
@ -258,6 +279,12 @@ GameLib.System.Linking.prototype.registerDependencies = function(component) {
*/
if (this.dependencies[id].indexOf(component === -1)) {
this.dependencies[id].push(component);
GameLib.Event.Emit(
GameLib.Event.UNRESOLVED_DEPENDENCIES_UPDATE,
{
dependencies : this.dependencies
}
);
}
/**
@ -278,6 +305,7 @@ GameLib.System.Linking.prototype.registerDependencies = function(component) {
component.instance = component.createInstance();
if (component.instance) {
component.loaded = true;
component.buildIdToObject();
GameLib.Event.EmitInstanceEvents(component);
}
}
@ -395,7 +423,7 @@ GameLib.System.Linking.prototype.onParentSceneChange = function(data) {
/**
* We remove the helper (if any) from the old scene and add it to the new scene
*/
var helper = this.findHelperByObject(data.object);
var helper = GameLib.EntityManager.Instance.findHelperByObject(data.object);
if (helper) {
if (data.originalScene && data.originalScene.instance) {
@ -411,58 +439,6 @@ GameLib.System.Linking.prototype.onParentSceneChange = function(data) {
data.originalScene.removeObject(data.object);
}
data.newScene.addObject(data.object);
/**
* We inherit the parent entity of this new scene
*/
var originalEntity = null;
var newEntity = null;
if (data.object.hasOwnProperty('parentEntity')) {
originalEntity = data.object.parentEntity
}
if (data.newScene.hasOwnProperty('parentEntity')) {
newEntity = data.newScene.parentEntity;
}
var gui = null;
if (originalEntity) {
if (originalEntity.removeComponent) {
if (helper) {
originalEntity.removeComponent(helper);
}
originalEntity.removeComponent(data.object);
}
if (originalEntity.getFirstComponent) {
gui = originalEntity.getFirstComponent(GameLib.GUI);
if (gui) {
gui.removeObject(data.object);
gui.build(this);
}
}
}
if (newEntity) {
if (newEntity.addComponent) {
if (helper) {
newEntity.addComponent(helper);
}
newEntity.addComponent(data.object);
}
if (newEntity.getFirstComponent) {
gui = newEntity.getFirstComponent(GameLib.GUI);
if (gui) {
gui.addObject(data.object);
gui.build(this);
}
}
}
}
};
@ -496,6 +472,12 @@ GameLib.System.Linking.prototype.onParentEntityChange = function(data) {
GameLib.System.Linking.prototype.stop = function() {
this.register = [];
GameLib.Event.Emit(
GameLib.Event.REGISTER_UPDATE,
{
register : this.register
}
);
this.componentCreatedSubscription.remove();
this.parentSceneChangeSubscription.remove();
this.parentEntityChangeSubscription.remove();

View File

@ -220,14 +220,12 @@ GameLib.System.Storage.prototype.loadComponent = function(toProcess, includeDepe
if (object.result !== 'success') {
if (onComponentError) {
onComponentError(error);
onComponentError(id, object);
}
GameLib.Event.Emit(
GameLib.Event.LOAD_COMPONENT_ERROR,
{
error: error
}
{error : object}
);
return;