464 lines
12 KiB
JavaScript
464 lines
12 KiB
JavaScript
/**
|
|
* System takes care of updating all the entities (based on their component data)
|
|
* @param apiSystem GameLib.API.System
|
|
* @constructor
|
|
*/
|
|
GameLib.System.GUI = function(
|
|
apiSystem
|
|
) {
|
|
GameLib.System.call(
|
|
this,
|
|
apiSystem
|
|
);
|
|
|
|
this.guis = [];
|
|
|
|
this.selected = [];
|
|
|
|
this.buildGUISubscription = null;
|
|
|
|
this.meshDeletedSubscription = null;
|
|
|
|
this.meshSelectedSubscription = null;
|
|
|
|
this.meshDeselectedSubscription = null;
|
|
|
|
this.newEntitySubscription = null;
|
|
|
|
this.meshSelectionObjects = {};
|
|
|
|
};
|
|
|
|
GameLib.System.GUI.prototype = Object.create(GameLib.System.prototype);
|
|
GameLib.System.GUI.prototype.constructor = GameLib.System.GUI;
|
|
|
|
GameLib.System.GUI.prototype.start = function() {
|
|
|
|
this.guis = GameLib.EntityManager.Instance.queryComponents(GameLib.GUI);
|
|
|
|
/**
|
|
* Add some GUI behaviour
|
|
*/
|
|
dat.GUI.prototype.removeEmtpyFolders = function() {
|
|
for (var property in this.__folders) {
|
|
if (this.__folders.hasOwnProperty(property)){
|
|
|
|
var folder = this.__folders[property];
|
|
|
|
if (folder.__listening.length === 0) {
|
|
folder.close();
|
|
this.__ul.removeChild(folder.domElement.parentNode);
|
|
delete this.__folders[property];
|
|
this.onResize();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
dat.GUI.prototype.removeAllFolders = function() {
|
|
for (var property in this.__folders) {
|
|
if (this.__folders.hasOwnProperty(property)){
|
|
|
|
var folder = this.__folders[property];
|
|
|
|
folder.close();
|
|
this.__ul.removeChild(folder.domElement.parentNode);
|
|
delete this.__folders[property];
|
|
this.onResize();
|
|
}
|
|
}
|
|
};
|
|
|
|
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.meshSelectionChange
|
|
);
|
|
|
|
this.meshDeselectedSubscription = this.subscribe(
|
|
GameLib.Event.MESH_DESELECTED,
|
|
this.meshSelectionChange
|
|
);
|
|
|
|
this.newEntitySubscription = this.subscribe(
|
|
GameLib.Event.NEW_ENTITY,
|
|
this.newEntity
|
|
)
|
|
};
|
|
|
|
GameLib.System.GUI.prototype.buildGUI = function(data) {
|
|
|
|
this.guis.map(function(gui){
|
|
|
|
/**
|
|
* Check if we have data
|
|
*/
|
|
if (GameLib.Utils.UndefinedOrNull(data.components)) {
|
|
console.log('no data components');
|
|
return;
|
|
}
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(data.components.length) || data.components.length === 0) {
|
|
console.log('no components selected');
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* First, start fresh - remove all folders
|
|
*/
|
|
gui.removeAllFolders();
|
|
|
|
/**
|
|
* Sort the components by component type
|
|
*/
|
|
data.components.sort(
|
|
|
|
function(a, b) {
|
|
|
|
if (a.componentType > b.componentType) {
|
|
return 1;
|
|
}
|
|
|
|
if (a.componentType < b.componentType) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Split the components into groups of componentType
|
|
*/
|
|
var componentGroups = data.components.reduce(
|
|
function(result, component) {
|
|
|
|
var componentData = result.pop();
|
|
|
|
if (component.componentType === componentData.componentType) {
|
|
/**
|
|
* This is the first component
|
|
*/
|
|
componentData.components.push(component);
|
|
result.push(componentData);
|
|
return result;
|
|
}
|
|
|
|
if (component.componentType !== componentData.componentType) {
|
|
result.push(componentData);
|
|
result.push({
|
|
componentType : component.componentType,
|
|
components:[component]
|
|
});
|
|
return result;
|
|
}
|
|
|
|
},
|
|
[
|
|
{
|
|
componentType : data.components[0].componentType,
|
|
components : []
|
|
}
|
|
]
|
|
);
|
|
|
|
componentGroups.map(
|
|
|
|
function(componentGroup){
|
|
|
|
if (componentGroup.components.length < 1) {
|
|
console.warn('invalid number of components');
|
|
}
|
|
|
|
var templateObject = {
|
|
template : {
|
|
/**
|
|
* Doing this here is just to put parentEntity at the top of the gui
|
|
*/
|
|
'parentEntity' : componentGroup.components[0].parentEntity
|
|
},
|
|
affected : [componentGroup.components[0]],
|
|
componentType : componentGroup.componentType
|
|
};
|
|
|
|
for (var property in componentGroup.components[0]) {
|
|
if (
|
|
componentGroup.components[0].hasOwnProperty(property) ||
|
|
typeof componentGroup.components[0][property] === 'function'
|
|
) {
|
|
|
|
if (typeof componentGroup.components[0][property] === 'function') {
|
|
|
|
templateObject.template[property] = function(__property) {
|
|
|
|
return function() {
|
|
|
|
this.affected.map(
|
|
function(component) {
|
|
component[__property].bind(component)();
|
|
}
|
|
)
|
|
|
|
}.bind(templateObject);
|
|
|
|
}(property);
|
|
|
|
} else {
|
|
|
|
templateObject.template[property] = componentGroup.components[0][property];
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
var componentTemplate = componentGroup.components.reduce(
|
|
|
|
function(result, component) {
|
|
|
|
if (component === componentGroup.components[0]) {
|
|
/**
|
|
* This is the first component, just return
|
|
*/
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Now start to filter out the properties
|
|
*/
|
|
for (var property in component) {
|
|
if (
|
|
component.hasOwnProperty(property)
|
|
) {
|
|
if (!result.template.hasOwnProperty(property)) {
|
|
continue;
|
|
}
|
|
|
|
if (
|
|
result.template[property] instanceof GameLib.Vector2 ||
|
|
result.template[property] instanceof GameLib.Vector3 ||
|
|
result.template[property] instanceof GameLib.Vector4
|
|
) {
|
|
if (!result.template[property].equals(component[property])) {
|
|
delete result.template[property];
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (result.template[property] !== component[property]) {
|
|
delete result.template[property];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store the affected component
|
|
*/
|
|
result.affected.push(component);
|
|
return result;
|
|
|
|
},
|
|
templateObject
|
|
);
|
|
|
|
/**
|
|
* componentTemplate now contains for this particular component type group - all
|
|
* the properties which are modifiable, and also the objects affected by this property changes
|
|
*/
|
|
var name;
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(componentTemplate.template.name)) {
|
|
name = GameLib.Component.GetComponentName(componentTemplate.componentType);
|
|
} else {
|
|
name = componentTemplate.template.name;
|
|
}
|
|
|
|
var folder = gui.addFolder(name);
|
|
|
|
if (!folder) {
|
|
throw new Error('Could not create folder');
|
|
}
|
|
|
|
for (var templateProperty in componentTemplate.template) {
|
|
|
|
if (
|
|
componentTemplate.template.hasOwnProperty(templateProperty) ||
|
|
typeof (componentTemplate.template[templateProperty]) === 'function'
|
|
) {
|
|
|
|
if (typeof (componentTemplate.template[templateProperty]) === 'function') {
|
|
folder.add(componentTemplate.template, templateProperty);
|
|
continue;
|
|
}
|
|
|
|
if (componentTemplate.template[templateProperty] instanceof GameLib.Vector2) {
|
|
gui.buildVectorControl(folder, componentTemplate, templateProperty, 2);
|
|
continue;
|
|
}
|
|
|
|
if (componentTemplate.template[templateProperty] instanceof GameLib.Vector3) {
|
|
gui.buildVectorControl(folder, componentTemplate, templateProperty, 3);
|
|
continue;
|
|
}
|
|
|
|
if (componentTemplate.template[templateProperty] instanceof GameLib.Vector4) {
|
|
gui.buildVectorControl(folder, componentTemplate, templateProperty, 4);
|
|
continue;
|
|
}
|
|
|
|
// if (
|
|
// component.linkedObjects &&
|
|
// component.linkedObjects[property]
|
|
// ) {
|
|
// if (property === 'parentEntity') {
|
|
// this.buildEntitySelectionControlFromArray(
|
|
// folder,
|
|
// component,
|
|
// property,
|
|
// entityManager
|
|
// )
|
|
// } else if (component.linkedObjects[property] instanceof Array) {
|
|
// this.buildArrayManager(
|
|
// folder,
|
|
// component,
|
|
// property,
|
|
// component.linkedObjects[property],
|
|
// entityManager
|
|
// )
|
|
// } else {
|
|
// this.buildSelectControl(folder, component, property, entityManager, component.linkedObjects[property]);
|
|
// }
|
|
//
|
|
// } else if (typeof (component[property]) === 'object') {
|
|
//
|
|
// if (this.isColor(component[property])) {
|
|
// this.buildControl(folder, component, property);
|
|
// } else {
|
|
// //console.log('ignored: ' + property);
|
|
// }
|
|
// } else {
|
|
// this.buildControl(folder, component, property, entityManager);
|
|
// }
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
};
|
|
|
|
GameLib.System.GUI.prototype.meshDeleted = function(data) {
|
|
|
|
};
|
|
|
|
GameLib.System.GUI.prototype.meshSelectionChange = function(data) {
|
|
|
|
var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh);
|
|
|
|
var components = [];
|
|
|
|
meshes.map(function(mesh){
|
|
|
|
if (!mesh.selected) {
|
|
return;
|
|
}
|
|
|
|
if (mesh.parentEntity) {
|
|
GameLib.Utils.PushUnique(components, mesh.parentEntity);
|
|
}
|
|
components.push(mesh);
|
|
|
|
mesh.materials.map(
|
|
function(material){
|
|
GameLib.Utils.PushUnique(components, material);
|
|
}
|
|
);
|
|
|
|
mesh.materials.map(
|
|
function(material){
|
|
for (var property in material.linkedObjects) {
|
|
if (
|
|
material.linkedObjects.hasOwnProperty(property) &&
|
|
material.hasOwnProperty(property) &&
|
|
material[property] &&
|
|
property !== 'parentEntity'
|
|
)
|
|
{
|
|
GameLib.Utils.PushUnique(components, material[property]);
|
|
for (var tProperty in material[property].linkedObjects) {
|
|
if (
|
|
material[property].linkedObjects.hasOwnProperty(tProperty) &&
|
|
material[property].hasOwnProperty(tProperty) &&
|
|
material[property][tProperty] &&
|
|
tProperty !== 'parentEntity'
|
|
) {
|
|
GameLib.Utils.PushUnique(components, material[property][tProperty]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
GameLib.Event.Emit(
|
|
GameLib.Event.BUILD_GUI,
|
|
{
|
|
components : components
|
|
}
|
|
);
|
|
};
|
|
|
|
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() {
|
|
|
|
this.guis.map(function(gui){
|
|
gui.domElement.instance.parentElement.removeChild(gui.instance.domElement);
|
|
});
|
|
|
|
delete dat.GUI.removeEmtpyFolders;
|
|
|
|
delete dat.GUI.removeAllFolders;
|
|
|
|
this.buildGUISubscription.remove();
|
|
|
|
this.meshDeletedSubscription.remove();
|
|
|
|
this.meshSelectedSubscription.remove();
|
|
|
|
this.meshDeselectedSubscription.remove();
|
|
|
|
this.newEntitySubscription.remove();
|
|
|
|
this.guis = [];
|
|
};
|
|
|