r3-legacy/build/game-lib.js

32508 lines
839 KiB
JavaScript

// COMPILE TIME DEFINITIONS (Generated via gulp)
var __DATE__ = "Tue Nov 28 2017 08:21:32 GMT+0100 (CET)";
// END COMPILE TIME DEFINITIONS
/**
* GameLib Namespace
*/
if (typeof GameLib === 'undefined') {
function GameLib() {}
}
/**
* GameLib.D3 Namespace
*/
if (typeof GameLib.D3 === 'undefined') {
GameLib.D3 = function(){};
}
/**
* GameLib.D3.API Namespace
* @constructor
*/
if (typeof GameLib.D3.API === 'undefined') {
GameLib.D3.API = function(){};
}
/**
* GameLib.API Namespace
*/
if (typeof GameLib.API === 'undefined') {
GameLib.API = function(){};
}
/**
* GameLib.D3.Runtime Namespace
* @constructor
*/
if (typeof GameLib.D3.Runtime === 'undefined') {
GameLib.D3.Runtime = function(){};
}
if (typeof Q === 'undefined') {
if (typeof require === 'undefined') {
console.warn('You need the Q promise library for the GameLib.D3');
throw new Error('You need the Q promise library for the GameLib.D3');
}
var Q = require('q');
}
if (typeof _ === 'undefined') {
if (typeof require === 'undefined') {
console.warn('You need the lodash library for the GameLib.D3');
throw new Error('You need the lodash library for the GameLib.D3');
}
var _ = require('lodash');
}
// This gets injected by gulp
console.log("Loading GameLib compiled at: " + __DATE__);
/**
* Event Core
* @constructor
*/
GameLib.Event = function() {
};
/**
* Some nice Events handling
* @type {{}}
*/
GameLib.Event.Subscriptions = {};
GameLib.Event.OnceSubscriptions = {};
/**
* Events we can subscribe to and publish
*/
GameLib.Event.WINDOW_RESIZE = 0x1;
GameLib.Event.PARENT_SCENE_CHANGE = 0x2;
GameLib.Event.PARENT_ENTITY_CHANGE = 0x3;
GameLib.Event.INSTANCE_CLONED = 0x4;
GameLib.Event.LOAD_IMAGE = 0x5;
GameLib.Event.NEW_ENTITY = 0x6;
GameLib.Event.MATERIAL_TYPE_CHANGED = 0x7;
GameLib.Event.SAVE_COMPONENT = 0x8;
GameLib.Event.SAVE_COMPONENT_ERROR = 0x9;
GameLib.Event.COMPONENT_SAVED = 0xa;
GameLib.Event.LOAD_COMPONENT = 0xb;
GameLib.Event.LOAD_COMPONENT_ERROR = 0xc;
GameLib.Event.LOGGED_IN = 0xd;
GameLib.Event.COMPONENT_CREATED = 0xe;
GameLib.Event.COMPONENT_CLONED = 0xf;
GameLib.Event.TEXTURE_ANIMATED_CHANGE = 0x10;
GameLib.Event.ANIMATE_TEXTURE_INSTANCE = 0x11;
GameLib.Event.REMOVE_PARTICLE_ENGINE = 0x12;
GameLib.Event.GAME_PAUSE = 0x13;
GameLib.Event.TEXTURE_INSTANCE_UPDATED = 0x14;
GameLib.Event.PLAY_AUDIO = 0x15;
GameLib.Event.MATERIAL_INSTANCE_UPDATED = 0x16;
GameLib.Event.PAUSE_AUDIO = 0x17;
GameLib.Event.MESH_INSTANCE_UPDATED = 0x18;
GameLib.Event.STOP_AUDIO = 0x19;
GameLib.Event.LIGHT_INSTANCE_UPDATED = 0x1a;
GameLib.Event.DELETE_COMPONENT = 0x1b;
GameLib.Event.COMPONENT_DOWNLOAD_COMPLETE = 0x1c;
GameLib.Event.COMPONENTS_LINKED = 0x1d;
GameLib.Event.UNRESOLVED_DEPENDENCIES_UPDATE = 0x1e;
GameLib.Event.REGISTER_UPDATE = 0x1f;
GameLib.Event.BUILD_GUI = 0x20;
GameLib.Event.REMOVE_MESH = 0x21;
GameLib.Event.MESH_SELECTED = 0x22;
GameLib.Event.MESH_DESELECTED = 0x23;
GameLib.Event.COMPONENT_REGISTER = 0x24;
GameLib.Event.IMAGE_NOT_FOUND = 0x25;
GameLib.Event.BLENDER_DATA_RECEIVED = 0x26;
GameLib.Event.IMAGE_UPLOAD_COMPLETE = 0x27;
GameLib.Event.REMOVE_COMPONENT = 0x28;
GameLib.Event.KEY_DOWN = 0x29;
GameLib.Event.KEY_UP = 0x2a;
GameLib.Event.RENDER = 0x2b;
GameLib.Event.EVENT_LIST = 0x2c;
GameLib.Event.COMPILE_SUCCESS = 0x2d;
GameLib.Event.COMPILE_FAILED = 0x2e;
GameLib.Event.IMAGE_CHANGED = 0x2f;
GameLib.Event.PARENT_ENTITY_CHANGED = 0x30;
GameLib.Event.MATERIAL_TEXTURES_UPDATED = 0x31;
GameLib.Event.DELETE_COMPONENT_ERROR = 0x32;
GameLib.Event.COMPONENT_DELETED = 0x33;
GameLib.Event.COMPONENT_TYPES_UPDATED = 0x34;
GameLib.Event.AUDIO_ENDED = 0x35;
GameLib.Event.COMPONENT_LINKED = 0x36;
GameLib.Event.DONE_SAVING = 0x37;
GameLib.Event.BEFORE_RENDER = 0x38;
GameLib.Event.AFTER_RENDER = 0x39;
GameLib.Event.ARRAY_ITEM_ADDED = 0x3a;
GameLib.Event.INSTANCE_CREATED = 0x3b;
GameLib.Event.VISUALIZE = 0x3c;
GameLib.Event.STOP_VISUALIZE = 0x3d;
GameLib.Event.FETCH_COMPONENT_TYPES = 0x3e;
GameLib.Event.FETCH_COMPONENTS = 0x3f;
GameLib.Event.GET_API_URL = 0x40;
GameLib.Event.GET_PHYSICS_IMPLEMENTATION = 0x41;
GameLib.Event.PARENT_WORLD_CHANGE = 0x42;
GameLib.Event.ANIMATE = 0x43;
GameLib.Event.ANIMATION_COMPILE_SUCCESS = 0x44;
GameLib.Event.ANIMATION_COMPILE_FAILED = 0x45;
GameLib.Event.SAVING = 0x46;
GameLib.Event.GAME_OVER = 0x47;
GameLib.Event.GAME_START = 0x48;
GameLib.Event.TOUCH_START = 0x49;
GameLib.Event.TOUCH_END = 0x4a;
GameLib.Event.TOUCH_MOVE = 0x4b;
GameLib.Event.TOUCH_CANCEL = 0x4c;
GameLib.Event.GET_REMOTE_API_URL = 0x4d;
GameLib.Event.GET_GRAPHICS_IMPLEMENTATION = 0x4e;
GameLib.Event.DELAYED_INSTANCE_ENCOUNTERED = 0x4f;
GameLib.Event.GET_CODER_IMPLEMENTATION = 0x50;
GameLib.Event.ANIMATION_MESH_ADDED = 0x51;
GameLib.Event.ANIMATION_MESH_REMOVED = 0x52;
GameLib.Event.GET_SCENE = 0x53;
GameLib.Event.CUSTOM_CODE_WINDOW_RESIZE = 0x54;
GameLib.Event.LOAD_FONT = 0x55;
GameLib.Event.FONT_NOT_FOUND = 0x56;
GameLib.Event.STOP_ALL_AUDIO = 0x57;
GameLib.Event.REGISTER_DEPENDENCIES = 0x58;
GameLib.Event.GAME_LOADED = 0x59;
//GameLib.Event.GAME_RESTART = 0x5a;
GameLib.Event.LOAD_PROGRESS = 0x5b;
GameLib.Event.ENTITY_LOADED = 0x5c;
GameLib.Event.MOUSE_DOWN = 0x5d;
GameLib.Event.MOUSE_MOVE = 0x5e;
GameLib.Event.MOUSE_WHEEL = 0x5f;
GameLib.Event.MOUSE_UP = 0x60;
GameLib.Event.PARTICLE_INSTANCE_UPDATED = 0x61;
GameLib.Event.GAME_DATA = 0x62;
GameLib.Event.PAUSE_ALL_AUDIO = 0x63;
GameLib.Event.CONTINUE_ALL_AUDIO = 0x64;
GameLib.Event.MUTE_AUDIO = 0x65;
GameLib.Event.GAME_STARTED = 0x66;
GameLib.Event.GAME_PAUSED = 0x67;
GameLib.Event.GAME_RESUMED = 0x68;
GameLib.Event.CUSTOM_GAME_START = 0x69;
GameLib.Event.AUDIO_MUTED = 0x6a;
GameLib.Event.AUDIO_UNMUTED = 0x6b;
/**
* Returns string name of event ID
* @param number
* @returns {*}
* @constructor
*/
GameLib.Event.GetEventName = function(number) {
switch(number) {
case 0x1 : return 'window_resize';
case 0x2 : return 'parent_scene_change';
case 0x3 : return 'parent_entity_change';
case 0x4 : return 'instance_cloned';
case 0x5 : return 'load_image';
case 0x6 : return 'new_entity';
case 0x7 : return 'material_type_changed';
case 0x8 : return 'save_component';
case 0x9 : return 'save_component_error';
case 0xa : return 'component_saved';
case 0xb : return 'load_component';
case 0xc : return 'load_component_error';
case 0xd : return 'logged_in';
case 0xe : return 'component_created';
case 0xf : return 'component_cloned';
case 0x10 : return 'texture_animated_change';
case 0x11 : return 'animate_texture_instance';
case 0x12 : return 'remove_particle_engine';
case 0x13 : return 'pause';
case 0x14 : return 'texture_instance_updated';
case 0x15 : return 'play_audio';
case 0x16 : return 'material_instance_updated';
case 0x17 : return 'pause_audio';
case 0x18 : return 'mesh_instance_updated';
case 0x19 : return 'stop_audio';
case 0x1a : return 'light_instance_updated';
case 0x1b : return 'delete_component';
case 0x1c : return 'component_download_complete';
case 0x1d : return 'components_linked';
case 0x1e : return 'unresolved_dependencies_update';
case 0x1f : return 'register_update';
case 0x20 : return 'build_gui';
case 0x21 : return 'remove_mesh';
case 0x22 : return 'mesh_selected';
case 0x23 : return 'mesh_deselected';
case 0x24 : return 'component_register';
case 0x25 : return 'image_not_found';
case 0x26 : return 'blender_data_received';
case 0x27 : return 'image_upload_complete';
case 0x28 : return 'remove_component';
case 0x29 : return 'key_down';
case 0x2a : return 'key_up';
case 0x2b : return 'render';
case 0x2c : return 'event_list';
case 0x2d : return 'compile_success';
case 0x2e : return 'compile_failed';
case 0x2f : return 'image_changed';
case 0x30 : return 'parent_entity_changed';
case 0x31 : return 'material_textures_updated';
case 0x32 : return 'delete_component_error';
case 0x33 : return 'component_deleted';
case 0x34 : return 'component_types_updated';
case 0x35 : return 'audio_ended';
case 0x36 : return 'component_linked';
case 0x37 : return 'done_saving';
case 0x38 : return 'before_render';
case 0x39 : return 'after_render';
case 0x3a : return 'array_item_added';
case 0x3b : return 'instance_created';
case 0x3c : return 'visualize';
case 0x3d : return 'stop_visualize';
case 0x3e : return 'fetch_component_types';
case 0x3f : return 'fetch_components';
case 0x40 : return 'get_api_url';
case 0x41 : return 'get_physics_implementation';
case 0x42 : return 'parent_world_change';
case 0x43 : return 'animate';
case 0x44 : return 'animation_compile_success';
case 0x45 : return 'animation_compile_failed';
case 0x46 : return 'saving';
case 0x47 : return 'game_over';
case 0x48 : return 'game_start';
case 0x49 : return 'touch_start';
case 0x4a : return 'touch_end';
case 0x4b : return 'touch_move';
case 0x4c : return 'touch_cancel';
case 0x4d : return 'get_remote_api_url';
case 0x4e : return 'get_graphics_implementation';
case 0x4f : return 'delayed_instance_encountered';
case 0x50 : return 'get_coder_implementation';
case 0x51 : return 'animation_mesh_added';
case 0x52 : return 'animation_mesh_removed';
case 0x53 : return 'get_scene';
case 0x54 : return 'custom_code_window_resize';
case 0x55 : return 'load_font';
case 0x56 : return 'font_not_found';
case 0x57 : return 'stop_all_audio';
case 0x58 : return 'register_dependencies';
case 0x59 : return 'game_loaded';
case 0x5a : return 'unused';//'game_restart';
case 0x5b : return 'load_progress';
case 0x5c : return 'entity_loaded';
case 0x5d : return 'mouse_down';
case 0x5e : return 'mouse_move';
case 0x5f : return 'mouse_wheel';
case 0x60 : return 'mouse_up';
case 0x61 : return 'particle_instance_updated';
case 0x62 : return 'game_data';
case 0x63 : return 'pause_all_audio';
case 0x64 : return 'continue_all_audio';
case 0x65 : return 'mute_audio';
case 0x66 : return 'game_started';
case 0x67 : return 'game_paused';
case 0x68 : return 'game_resumed';
case 0x69 : return 'custom_game_start';
case 0x6a : return 'audio_muted';
case 0x6b : return 'audio_unmuted';
break;
}
throw new error('unknown event id: ' + number );
};
/**
* Subscribe to some events
* @param eventName
* @param callback
*/
GameLib.Event.prototype.subscribe = function(
eventName,
callback
) {
return GameLib.Event.Subscribe(eventName, callback.bind(this));
};
// /**
// * 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
// // );
// // }
// // }
// };
/**
*
* @param eventName
* @param data
*/
/**
* Publish some event happened with some data
* @param eventName
* @param data
* @param clientCallback
* @param clientErrorCallback
* @returns {number} of callbacks executed
*/
GameLib.Event.prototype.publish = function(
eventName,
data,
clientCallback,
clientErrorCallback
) {
return GameLib.Event.Emit(
eventName,
data,
clientCallback,
clientErrorCallback
);
};
/**
* Static method call
* @param eventName
* @param data
* @param clientCallback is executed ideally when the event completed
* @param clientErrorCallback
* @returns {number} of callbacks executed
* @constructor
*/
GameLib.Event.Emit = function(
eventName,
data,
clientCallback,
clientErrorCallback
) {
var count = 0;
if (GameLib.Event.Subscriptions.hasOwnProperty(eventName)) {
if (GameLib.Event.Subscriptions[eventName].length === 0) {
if (clientCallback) {
/**
* We execute the client callback immediately since there are no subscriptions to this event
*/
clientCallback();
}
if (clientErrorCallback) {
clientErrorCallback({
message : 'No subscriptions for event ' + eventName
})
}
}
/**
* We need to execute all the callbacks, but not execute them twice, but also keep in mind they can remove
* themselves during execution
*/
// var length = GameLib.Event.Subscriptions[eventName].length;
//
// for (var i = 0; i < length; i++) {
//
// var object = GameLib.Event.Subscriptions[eventName][i];
//
// if (object.fn && object.executed === false) {
// object.fn(data, clientCallback, clientErrorCallback);
// object.executed = true;
// }
//
// if (length !== GameLib.Event.Subscriptions[eventName].length) {
// /**
// * this callback removed a subscription - reset i and reset the length
// */
// i = 0;
// length = GameLib.Event.Subscriptions[eventName].length;
// }
// }
//
// GameLib.Event.Subscriptions[eventName].map(
// function(object){
// object.executed = false;
// }
// )
GameLib.Event.Subscriptions[eventName].map(
function(callback) {
if (callback) {
callback(data, clientCallback, clientErrorCallback);
count++;
}
}
)
} else {
if (clientCallback) {
/**
* We execute the client callback immediately since there are no subscriptions to this event
*/
clientCallback();
}
if (clientErrorCallback) {
clientErrorCallback({
message : 'No subscriptions for event ' + eventName
})
}
}
return count;
};
GameLib.Event.Subscribe = function(
eventName,
fn
) {
if (GameLib.Event.Subscriptions.hasOwnProperty(eventName)) {
GameLib.Event.Subscriptions[eventName].push(fn);
// {
// fn : fn,
// executed : false
// }
// );
} else {
GameLib.Event.Subscriptions[eventName] = [];
GameLib.Event.Subscriptions[eventName].push(fn);
// {
// fn : fn,
// executed : false
// }
// );
}
/**
* Return a handle to the caller to allow us to unsubscribe to this event
*/
return {
fn : fn,
remove : function() {
var index = GameLib.Event.Subscriptions[eventName].indexOf(fn);
// reduce(
// function(result, object, index) {
// if (object.fn === fn) {
// result = index;
// }
// return result;
// },
// -1
// );
if (index === -1) {
throw new Error('could not remove subscription');
}
GameLib.Event.Subscriptions[eventName].splice(
index,
1
);
}
}
};
GameLib.Utils = function() {};
/**
* Strips image extension from given path
* @param imagePath
* @constructor
*/
GameLib.Utils.StripImageExtension = function(imagePath) {
return imagePath.replace(/(\.png$|\.gif$|\.jpeg$|\.jpg$)/,'')
};
/**
* Returns id of object with the name if it exists in the array, otherwise null
* @param name
* @param array
* @returns {*}
* @constructor
*/
GameLib.Utils.ObjectIdWithNameInArray = function(name, array) {
return array.reduce(
function(result, object) {
if (result) {
return result;
}
if (name === object.name) {
return object.id;
}
return null;
},
null
);
};
// GameLib.Utils.ObjectFactory = function() {
//
// var promiseList = {};
//
// return function(objectId) {
//
// if (!objectId) {
// console.log('No Object ID specified ' + objectId);
// throw new Error('No Object ID specified ' + objectId);
// }
//
// if (promiseList[objectId]) {
// return promiseList[objectId];
// }
//
// var defer = Q.defer();
//
// promiseList[objectId] = defer.promise;
//
// GameLib.Utils.ObjectFactory.Link(idToObject, objectId, defer);
//
// return promiseList[objectId];
// }
// };
GameLib.Utils.LoadIdsFromArrayToIdObject = function(array, idToObject) {
};
GameLib.Utils.LoadIdsFromObjectToIdObject = function(object, idToObject) {
};
/**
* Gets random int exclusive of maximum
* @param min
* @param max
* @returns {*}
* @constructor
*/
GameLib.Utils.GetRandomInt = function(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
};
/**
* Gets random int inclusive of maximum
* @param min
* @param max
* @returns {*}
* @constructor
*/
GameLib.Utils.GetRandomIntInclusive = function(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive
};
GameLib.Utils.InterpolateArray = function(data, fitCount) {
var linearInterpolate = function (before, after, atPoint) {
return before + (after - before) * atPoint;
};
var newData = [];
var springFactor = Number((data.length - 1) / (fitCount - 1));
newData[0] = data[0]; // for new allocation
for ( var i = 1; i < fitCount - 1; i++) {
var tmp = i * springFactor;
var before = Number(Math.floor(tmp)).toFixed();
var after = Number(Math.ceil(tmp)).toFixed();
var atPoint = tmp - before;
newData[i] = linearInterpolate(data[before], data[after], atPoint);
}
newData[fitCount - 1] = data[data.length - 1]; // for new allocation
return newData;
};
/**
* Undefined or null check
* @param variable
* @returns {boolean}
* @constructor
*/
GameLib.Utils.UndefinedOrNull = function (
variable
) {
return typeof variable === 'undefined' || variable === null;
};
/**
* Returns either an ID of the object or Null
* @param object
* @returns {null}
* @constructor
*/
GameLib.Utils.IdOrNull = function (object) {
if (GameLib.Utils.UndefinedOrNull(object)) {
return null;
} else {
if (GameLib.Utils.UndefinedOrNull(object.id)) {
console.warn('saving an object reference with no ID : ', object);
return null;
}
return object.id;
}
};
/**
* Limit a property to values between -pi and +pi
* @param property
* @param objectProperty
* @returns {{configurable?: boolean, enumerable?: boolean, value?, writable?: boolean, get?: Function, set?: Function}}
* @constructor
*/
GameLib.Utils.LimitToPI = function(property, objectProperty) {
var store = objectProperty;
return {
get : function() {
return store;
},
set : function(value) {
while (value > Math.PI) {
value -= (Math.PI * 2);
}
while (value < -(Math.PI)) {
value += (Math.PI * 2);
}
store = value;
}
};
};
/**
* Returns an array of IDs representing the objects
* @param array
* @returns []
* @constructor
*/
GameLib.Utils.IdArrayOrEmptyArray = function (array) {
if (GameLib.Utils.UndefinedOrNull(array)) {
return [];
} else {
return array.map(function(item) {
if (GameLib.Utils.UndefinedOrNull(item.id)) {
throw new Error('No ID found while trying to store IDs to array');
}
return item.id
});
}
};
/**
* Links an object to its parent through idToObject array
* @param propertyString
* @param idToObject
* @param parentObject
* @param id
* @constructor
*/
GameLib.Utils.Link = function(propertyString, idToObject, parentObject, id) {
if (!GameLib.Utils.UndefinedOrNull(parentObject[propertyString])) {
if (!idToObject.hasOwnProperty(id)) {
console.warn('Linking failed for object:' + parentObject.name);
}
parentObject[propertyString] = idToObject[id];
}
};
/**
* Generates a random ID
* @returns {string}
* @constructor
*/
GameLib.Utils.RandomId = function(length) {
if (GameLib.Utils.UndefinedOrNull(length)) {
length = 10;
}
return Math.random().toString(36).substr(2, length);
};
GameLib.Utils.InvertWindingOrder = function(triangles) {
for (var i = 0; i < triangles.length; i++) {
var v1 = triangles[i].v1;
triangles[i].v1 = triangles[i].v2;
triangles[i].v2 = v1;
var backupUV = triangles[i].triangle.v1uv;
triangles[i].triangle.v1uv = triangles[i].triangle.v2uv;
triangles[i].triangle.v2uv = backupUV;
}
return triangles;
};
/**
* Inverts a mesh winding order (and its instance)
* @param mesh GameLib.D3.Mesh
* @returns {*}
* @constructor
*/
GameLib.Utils.InvertMeshWindingOrder = function(mesh) {
mesh.faces.forEach(
function (face) {
var tmpV1 = face.v1;
face.v1 = face.v2;
face.v2 = tmpV1;
var tmpV1uv = face.v1uv;
face.v1uv = face.v2uv;
face.v2uv = tmpV1uv;
}.bind(this)
);
mesh.computeNormals = true;
mesh.createInstance();
};
/**
* This function resets a the winding order of a mesh from a reference point V (the average center of the mesh)
*/
GameLib.Utils.ResetWindingOrder = function(faces, vertices) {
var vertexList = new GameLib.API.Vector3.Points();
for (var v = 0; v < vertices.length; v++) {
vertexList.add(new GameLib.API.Vector3(
vertices[v].position.x,
vertices[v].position.y,
vertices[v].position.z
));
}
var V = vertexList.average();
var triangles = [];
for (var s = 0; s < faces.length; s += 3) {
var v0 = faces[s];
var v1 = faces[s+1];
var v2 = faces[s+2];
triangles.push(
{
v0 : v0,
v1 : v1,
v2 : v2,
edges : [
{v0: v0, v1: v1},
{v0: v1, v1: v2},
{v0: v2, v1: v0}
],
winding : 0,
edgeIndex : -1,
processed : false
}
);
}
for (var i = 0; i < triangles.length; i++) {
if (
GameLib.API.Vector3.clockwise(
vertices[triangles[i].v0].position,
vertices[triangles[i].v1].position,
vertices[triangles[i].v2].position,
V
)
) {
console.log('clockwise');
var bv1 = triangles[i].v1;
triangles[i].v1 = triangles[i].v2;
triangles[i].v2 = bv1;
} else {
console.log('not clockwise');
}
}
return triangles;
};
/**
* This function resets the winding order for triangles in faces, given an initial triangle and orientation edge
* used pseudocode from
* http://stackoverflow.com/questions/17036970/how-to-correct-winding-of-triangles-to-counter-clockwise-direction-of-a-3d-mesh
* We need to use a graph traversal algorithm,
* lets assume we have method that returns neighbor of triangle on given edge
*
* neighbor_on_egde( next_tria, edge )
*
* to_process = set of pairs triangle and orientation edge, initial state is one good oriented triangle with any edge on it
* processed = set of processed triangles; initial empty
*
* while to_process is not empty:
* next_tria, orientation_edge = to_process.pop()
* add next_tria in processed
* if next_tria is not opposite oriented than orientation_edge:
* change next_tria (ABC) orientation (B<->C)
* for each edge (AB) in next_tria:
* neighbor_tria = neighbor_on_egde( next_tria, edge )
* if neighbor_tria exists and neighbor_tria not in processed:
* to_process add (neighbor_tria, edge opposite oriented (BA))
* @param faces GameLib.D3.Face[]
* @param orientationEdge GameLib.API.Vector2
* @returns {Array}
*/
GameLib.Utils.FixWindingOrder = function(faces, orientationEdge) {
/**
* Checks if a Face belonging to a TriangleEdge has already been processed
* @param processed TriangleEdge[]
* @param triangle Face
* @returns {boolean}
*/
function inProcessed(processed, triangle) {
for (var i = 0; i < processed.length; i++) {
if (processed[i].triangle.equals(triangle)) {
return true;
}
}
return false;
}
/**
* Returns a neighbouring triangle on a specific edge - preserving the edge orientation
* @param edge GameLib.API.Vector2
* @param faces GameLib.D3.Face[]
* @param currentTriangle
* @returns {*}
*/
function neighbourOnEdge(edge, faces, currentTriangle) {
for (var i = 0; i < faces.length; i++) {
if (
(faces[i].v0 === edge.x && faces[i].v1 === edge.y) ||
(faces[i].v1 === edge.x && faces[i].v2 === edge.y) ||
(faces[i].v2 === edge.x && faces[i].v0 === edge.y) ||
(faces[i].v0 === edge.y && faces[i].v1 === edge.x) ||
(faces[i].v1 === edge.y && faces[i].v2 === edge.x) ||
(faces[i].v2 === edge.y && faces[i].v0 === edge.x)
) {
var triangle = new GameLib.D3.API.Face(
null,
null,
faces[i].v0index,
faces[i].v1index,
faces[i].v2index,
faces[i].materialIndex,
faces[i].uvs
);
if (triangle.equals(currentTriangle)) {
continue;
}
return new GameLib.D3.TriangleEdge(
triangle,
edge
);
}
}
return null;
}
var toProcess = [
new GameLib.D3.TriangleEdge(
new GameLib.D3.API.Face(
null,
null,
faces[0].v0index,
faces[0].v1index,
faces[0].v2index,
faces[0].materialIndex,
faces[0].uvs
),
orientationEdge
)
];
var processed = [];
while (toProcess.length > 0) {
var triangleEdge = toProcess.pop();
/**
* If edge is the same orientation (i.e. the edge order is the same as the given triangle edge) it needs to be reversed
* to have the same winding order)
*/
if (
(triangleEdge.triangle.v0index === triangleEdge.edge.x &&
triangleEdge.triangle.v1index === triangleEdge.edge.y) ||
(triangleEdge.triangle.v1index === triangleEdge.edge.x &&
triangleEdge.triangle.v2index === triangleEdge.edge.y) ||
(triangleEdge.triangle.v2index === triangleEdge.edge.x &&
triangleEdge.triangle.v0index === triangleEdge.edge.y)
) {
var backupV = triangleEdge.triangle.v1index;
triangleEdge.triangle.v1index = triangleEdge.triangle.v2index;
triangleEdge.triangle.v2index = backupV;
// var backupUV = triangleEdge.triangle.v1uv;
// triangleEdge.triangle.v1uv = triangleEdge.triangle.v2uv;
// triangleEdge.triangle.v2uv = backupUV;
//
var backupUV = triangleEdge.triangle.uvs[0][1];
triangleEdge.triangle.uvs[0][1] = triangleEdge.triangle.uvs[0][2];
triangleEdge.triangle.uvs[0][2] = backupUV;
}
processed.push(triangleEdge);
var edges = [
new GameLib.API.Vector2(
triangleEdge.triangle.v0index,
triangleEdge.triangle.v1index
),
new GameLib.API.Vector2(
triangleEdge.triangle.v1index,
triangleEdge.triangle.v2index
),
new GameLib.API.Vector2(
triangleEdge.triangle.v2index,
triangleEdge.triangle.v0index
)
];
for (var j = 0; j < edges.length; j++) {
var neighbour = neighbourOnEdge(edges[j], faces, triangleEdge.triangle);
if (neighbour && !inProcessed(processed, neighbour.triangle)) {
toProcess.push(neighbour);
}
}
}
/**
* In processed - we will have some duplicates - only add the unique ones
* @type {Array}
*/
var triangles = [];
for (var i = 0; i < processed.length; i++) {
var found = false;
for (var k = 0; k < triangles.length; k++) {
if (triangles[k].equals(processed[i].triangle)){
found = true;
break;
}
}
if (!found) {
triangles.push(processed[i].triangle);
}
}
return triangles;
};
/**
* This is a work-around function to fix polys which don't triangulate because
* they could lie on Z-plane (XZ or YZ)) - we translate the poly to the origin, systematically rotate the poly around
* Z then Y axis
* @param verticesFlat []
* @param grain is the amount to systematically rotate the poly by - a finer grain means a more accurate maximum XY
* @return []
*/
GameLib.Utils.FixPolyZPlane = function(verticesFlat, grain) {
if ((verticesFlat.length % 3) !== 0 && !(verticesFlat.length > 9)) {
console.log("The vertices are not in the right length : " + verticesFlat.length);
}
var vertices = [];
var points = new GameLib.API.Quaternion.Points();
for (var i = 0; i < verticesFlat.length; i += 3) {
points.add(new GameLib.API.Vector3(
verticesFlat[i],
verticesFlat[i + 1],
verticesFlat[i + 2]
));
}
points.toOrigin();
points.maximizeXDistance(grain);
points.maximizeYDistance(grain);
for (i = 0; i < points.vectors.length; i++) {
vertices.push(
[
points.vectors[i].x,
points.vectors[i].y
]
);
}
return vertices;
};
GameLib.Utils.MovingAverage = function(period) {
var nums = [];
return function(num) {
nums.push(num);
if (nums.length > period)
nums.splice(0,1); // remove the first element of the array
var sum = 0;
for (var i in nums)
sum += nums[i];
var n = period;
if (nums.length < period)
n = nums.length;
return(sum/n);
}
};
GameLib.Utils.Intersect = function (a, b) {
var t;
/**
* Loop over shortest array
*/
if (b.length > a.length) {
t = b;
b = a;
a = t;
}
return a.filter(
/**
* Check if exists
* @param e
* @returns {boolean}
*/
function (e) {
return (b.indexOf(e) > -1);
}
).filter(
/**
* Remove Duplicates
* @param e
* @param i
* @param c
* @returns {boolean}
*/
function (e, i, c) {
return c.indexOf(e) === i;
}
);
};
GameLib.Utils.Difference = function (a, b) {
var t;
/**
* Loop over shortest array
*/
if (b.length > a.length) {
t = b;
b = a;
a = t;
}
return a.filter(
/**
* Check if exists
* @param e
* @returns {boolean}
*/
function (e) {
return (b.indexOf(e) === -1);
}
).filter(
/**
* Remove Duplicates
* @param e
* @param i
* @param c
* @returns {boolean}
*/
function (e, i, c) {
return c.indexOf(e) === i;
}
);
};
/**
* Push only if not in there already
* @param array
* @param object
* @constructor
*/
GameLib.Utils.PushUnique = function(array, object) {
if (array.indexOf(object) === -1) {
array.push(object);
}
};
/**
* Checks whether or not the object is empty
* @param obj
* @returns {boolean}
* @constructor
*/
GameLib.Utils.IsEmpty = function(obj) {
return (Object.keys(obj).length === 0 && obj.constructor === Object);
};
GameLib.Utils.isString = function(member) {
return (typeof member === 'string');
};
GameLib.Utils.isBoolean = function(member) {
return (member === true || member === false);
};
GameLib.Utils.isColor = function(member) {
return (member instanceof GameLib.Color);
};
GameLib.Utils.isNumber = function(member) {
return (typeof member === 'number');
};
GameLib.Utils.isVector2 = function(member) {
return (
member instanceof GameLib.API.Vector2 ||
member instanceof GameLib.Vector2
);
};
GameLib.Utils.isVector3 = function(member) {
return (
member instanceof GameLib.API.Vector3 ||
member instanceof GameLib.Vector3
);
};
GameLib.Utils.isVector4 = function(member) {
return (
member instanceof GameLib.API.Vector4 ||
member instanceof GameLib.Vector4 ||
member instanceof GameLib.API.Quaternion ||
member instanceof GameLib.Quaternion
);
};
/**
* @return {string}
*/
GameLib.Utils.LowerUnderscore = function(name) {
return name.toLowerCase().replace(/\s+/, '_');
};
GameLib.Utils.UpperCaseWordsSpaces = function(word) {
return word.replace(/[-_]/g, ' ').split(' ').reduce(
function(result, word) {
result += word[0].toUpperCase() + word.substr(1);
return result + ' ';
},
''
).trim();
};
/**
* API Component Interface - Do not construct objects of this type directly
* @param componentType
* @param parentEntity
* @constructor
*/
GameLib.API.Component = function(
componentType,
parentEntity
) {
this.componentType = componentType;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.API.Component.prototype = Object.create(GameLib.Event.prototype);
GameLib.API.Component.prototype.constructor = GameLib.API.Component;
/**
* Component Interface
* @constructor
* @param componentType
* @param linkedObjects
* @param delayed
*/
GameLib.Component = function(
componentType,
linkedObjects,
delayed
) {
if (GameLib.Utils.UndefinedOrNull(linkedObjects)) {
linkedObjects = {};
}
this.linkedObjects = linkedObjects;
this.linkedObjects.parentEntity = GameLib.Entity;
GameLib.API.Component.call(
this,
componentType,
this.parentEntity
);
this.idToObject = {};
this.selected = false;
this.building = false;
this.loaded = false;
this.linked = false;
this.cloneNumber = 0;
this.isClone = false;
if (GameLib.Utils.UndefinedOrNull(delayed)) {
delayed = false;
}
this.delayed = delayed;
this.dependencies = this.getDependencies();
GameLib.Event.Emit(
GameLib.Event.COMPONENT_REGISTER,
{
component : this
}
);
if (this.dependencies.length === 0) {
this.performInstanceCreation();
} else {
GameLib.Event.Emit(
GameLib.Event.REGISTER_DEPENDENCIES,
{
component : this
}
);
}
};
GameLib.Component.prototype = Object.create(GameLib.API.Component.prototype);
GameLib.Component.prototype.constructor = GameLib.Component;
/**
* This function, performs standard instance creation steps for all our components, which means
* Ensure we have no dependencies
* Build a list of all child components - if they are all linked, we are ready to create an instance
* Ensure we are linked
* Ensure we are not delayed
* Try to create the instance
* Error Log if failed
* Don't do anything if we are not fully linked
*/
GameLib.Component.prototype.performInstanceCreation = function() {
var dependencies = true;
if (GameLib.Utils.UndefinedOrNull(this.dependencies)) {
dependencies = false;
}
if (this.dependencies && this.dependencies instanceof Array && this.dependencies.length === 0) {
dependencies = false;
}
if (dependencies) {
throw new Error('performInstanceCreation called while this object still has dependencies');
}
delete this.dependencies;
/**
* Build ID to object should run through all sub components -
* if one is found which is not linked, this component is not linked fully
*/
this.buildIdToObject();
/**
* Don't try to create an instance of this object until it is fully linked
*/
if (this.linked) {
if (!this.delayed) {
try {
this.createInstance();
} catch (error) {
console.error(error);
}
} else {
/**
* Some systems require a restart in order to create the delayed components (like System.Input for
* Edit Controls) - we need to give them the opportunity to restart
*/
GameLib.Event.Emit(
GameLib.Event.DELAYED_INSTANCE_ENCOUNTERED,
{
component : this
}
)
}
}
};
GameLib.Component.prototype.createInstance = function() {
// console.log('create instance : '+ this.name);
/**
* When you do actually call 'createInstance' - it is wise to state we are no longer delayed - we assume the caller
* knows when to call createInstance, so we do the housekeeping here
* @type {boolean}
*/
this.delayed = false;
if (this.instance) {
this.loaded = true;
GameLib.Event.Emit(
GameLib.Event.INSTANCE_CREATED,
{
component: this
}
)
}
if (this instanceof GameLib.Entity) {
GameLib.Event.Emit(
GameLib.Event.ENTITY_LOADED,
{
entity:this
}
)
}
};
/**
* Dependencies are everything which is either a string or an object with an id which is linked to this object
* @returns {Array}
*/
GameLib.Component.prototype.getDependencies = function() {
var dependencies = [];
for (var property in this.linkedObjects) {
if (
this.linkedObjects.hasOwnProperty(property) &&
property.indexOf('parent') !== 0 &&
this.hasOwnProperty(property)
){
if (typeof this[property] === 'string') {
GameLib.Utils.PushUnique(dependencies, this[property]);
}
if (this[property] instanceof Array) {
this[property].map(
function(arrayProperty) {
if (typeof arrayProperty === 'string') {
GameLib.Utils.PushUnique(dependencies, arrayProperty);
}
if (arrayProperty &&
arrayProperty instanceof GameLib.Component
) {
GameLib.Utils.PushUnique(dependencies, arrayProperty.id);
}
}
);
}
if (this[property] &&
this[property] instanceof GameLib.Component
) {
GameLib.Utils.PushUnique(dependencies, this[property].id);
}
}
}
return dependencies;
};
GameLib.Component.prototype.toString = function() {
return this.id;
};
GameLib.Component.COMPONENT_PATH_FOLLOWING = 0x1;
GameLib.Component.COMPONENT_MATERIAL = 0x2;
GameLib.Component.COMPONENT_RENDERER = 0x3;
GameLib.Component.COMPONENT_LOOK_AT = 0x4;
GameLib.Component.COMPONENT_CAMERA = 0x5;
GameLib.Component.COMPONENT_FOLLOW = 0x6;
GameLib.Component.COMPONENT_MESH = 0x7;
GameLib.Component.COMPONENT_SPLINE = 0x8;
GameLib.Component.COMPONENT_LIGHT = 0x9;
GameLib.Component.COMPONENT_INPUT_DRIVE = 0xa;
GameLib.Component.COMPONENT_COMPOSER = 0xb;
GameLib.Component.COMPONENT_RENDER_TARGET = 0xc;
GameLib.Component.COMPONENT_PASS = 0xd;
GameLib.Component.COMPONENT_SCENE = 0xe;
GameLib.Component.COMPONENT_RAYCASTER = 0xf;
GameLib.Component.COMPONENT_INPUT_EDITOR = 0x10;
GameLib.Component.COMPONENT_EDITOR = 0x11;
GameLib.Component.COMPONENT_VIEWPORT = 0x12;
GameLib.Component.COMPONENT_SYSTEM = 0x13;
GameLib.Component.COMPONENT_GRAPHICS = 0x14;
GameLib.Component.COMPONENT_HELPER = 0x15;
GameLib.Component.COMPONENT_CUSTOM_CODE = 0x16;
GameLib.Component.COMPONENT_MOUSE = 0x17;
GameLib.Component.COMPONENT_SKELETON = 0x18;
GameLib.Component.COMPONENT_TEXTURE = 0x19;
GameLib.Component.COMPONENT_ENTITY_MANAGER = 0x1a;
GameLib.Component.COMPONENT_DOM_ELEMENT = 0x1b;
GameLib.Component.COMPONENT_IMAGE_FACTORY = 0x1c;
GameLib.Component.COMPONENT_STATS = 0x1d;
GameLib.Component.COMPONENT_GUI = 0x1e;
GameLib.Component.COMPONENT_IMAGE = 0x1f;
GameLib.Component.COMPONENT_ENTITY = 0x20;
GameLib.Component.COMPONENT_MESH_SPHERE = 0x21;
GameLib.Component.COMPONENT_MESH_PLANE = 0x22;
GameLib.Component.COMPONENT_MESH_CURVE = 0x23;
GameLib.Component.COMPONENT_PHYSICS_WORLD = 0x24;
GameLib.Component.COMPONENT_BROADPHASE = 0x25;
GameLib.Component.COMPONENT_SOLVER = 0x26;
GameLib.Component.COMPONENT_RIGID_BODY = 0x27;
GameLib.Component.COMPONENT_SHAPE = 0x28;
GameLib.Component.COMPONENT_SHAPE_BOX = 0x29;
GameLib.Component.COMPONENT_SHAPE_SPHERE = 0x2a;
GameLib.Component.COMPONENT_SHAPE_TRI_MESH = 0x2b;
GameLib.Component.COMPONENT_SHAPE_CONVEX_HULL = 0x2c;
GameLib.Component.COMPONENT_SHAPE_CONVEX_HULL_CYLINDER = 0x2d;
GameLib.Component.COMPONENT_SHAPE_HEIGHT_MAP = 0x2e;
GameLib.Component.COMPONENT_SHAPE_PLANE = 0x2f;
GameLib.Component.COMPONENT_CONTROLS = 0x30;
GameLib.Component.COMPONENT_CONTROLS_EDITOR = 0x31;
GameLib.Component.COMPONENT_CONTROLS_TOUCH = 0x32;
GameLib.Component.COMPONENT_FRICTION_MATERIAL = 0x33;
GameLib.Component.COMPONENT_FRICTION_CONTACT_MATERIAL = 0x34;
GameLib.Component.COMPONENT_RAYCAST_VEHICLE = 0x35;
GameLib.Component.COMPONENT_RAYCAST_WHEEL = 0x36;
GameLib.Component.COMPONENT_CLOCK = 0x37;
GameLib.Component.COMPONENT_ANIMATION = 0x38;
GameLib.Component.COMPONENT_CONTROLS_KEYBOARD = 0x39;
GameLib.Component.COMPONENT_CONTROLS_MOUSE = 0x3a;
GameLib.Component.COMPONENT_MESH_TEXT = 0x3b;
GameLib.Component.COMPONENT_FONT = 0x3c;
GameLib.Component.COMPONENT_CANVAS = 0x3d;
GameLib.Component.COMPONENT_BONE = 0x3e;
GameLib.Component.COMPONENT_MESH_BOX = 0x3f;
GameLib.Component.COMPONENT_MESH_CYLINDER = 0x40;
GameLib.Component.COMPONENT_SYSTEM_ANIMATION = 0x41;
GameLib.Component.COMPONENT_SYSTEM_CUSTOM_CODE = 0x42;
GameLib.Component.COMPONENT_SYSTEM_GUI = 0x43;
GameLib.Component.COMPONENT_SYSTEM_INPUT = 0x44;
GameLib.Component.COMPONENT_SYSTEM_LINKING = 0x45;
GameLib.Component.COMPONENT_SYSTEM_PHYSICS = 0x46;
GameLib.Component.COMPONENT_SYSTEM_RENDER = 0x47;
GameLib.Component.COMPONENT_SYSTEM_STORAGE = 0x48;
GameLib.Component.COMPONENT_SYSTEM_VISUALIZATION = 0x49;
GameLib.Component.COMPONENT_FOG = 0x50;
GameLib.Component.COMPONENT_MESH_LINE = 0x51;
GameLib.Component.COMPONENT_PARTICLE_ENGINE = 0x52;
GameLib.Component.COMPONENT_SYSTEM_PARTICLE = 0x53;
GameLib.Component.COMPONENT_PARTICLE = 0x54;
GameLib.Component.COMPONENT_AUDIO = 0x55;
GameLib.Component.COMPONENT_SYSTEM_AUDIO = 0x56;
/**
* Returns string name for component number
* @param number
* @returns {*}
* @constructor
*/
GameLib.Component.GetComponentName = function(number) {
switch(number) {
case 0x1 : return 'GameLib.D3.PathFollowing';
case 0x2 : return 'GameLib.D3.Material';
case 0x3 : return 'GameLib.D3.Renderer';
case 0x4 : return 'GameLib.D3.LookAt';
case 0x5 : return 'GameLib.D3.Camera';
case 0x6 : return 'GameLib.D3.Follow';
case 0x7 : return 'GameLib.D3.Mesh';
case 0x8 : return 'GameLib.D3.Spline';
case 0x9 : return 'GameLib.D3.Light';
case 0xa : return 'GameLib.D3.InputDrive';
case 0xb : return 'GameLib.D3.Composer';
case 0xc : return 'GameLib.D3.RenderTarget';
case 0xd : return 'GameLib.D3.Pass';
case 0xe : return 'GameLib.D3.Scene';
case 0xf : return 'GameLib.D3.Raycaster';
case 0x10 : return 'GameLib.D3.InputEditor';
case 0x11 : return 'GameLib.D3.Editor';
case 0x12 : return 'GameLib.D3.Viewport';
case 0x13 : return 'GameLib.System';
case 0x14 : return 'GameLib.D3.Graphics';
case 0x15 : return 'GameLib.D3.Helper';
case 0x16 : return 'GameLib.D3.CustomCode';
case 0x17 : return 'GameLib.Mouse';
case 0x18 : return 'GameLib.D3.Skeleton';
case 0x19 : return 'GameLib.D3.Texture';
case 0x1a : return 'GameLib.EntityManager';
case 0x1b : return 'GameLib.DomElement';
case 0x1c : return 'GameLib.D3.ImageFactory';
case 0x1d : return 'GameLib.D3.Stats';
case 0x1e : return 'GameLib.GUI';
case 0x1f : return 'GameLib.D3.Image';
case 0x20 : return 'GameLib.Entity';
case 0x21 : return 'GameLib.D3.Mesh.Sphere';
case 0x22 : return 'GameLib.D3.Mesh.Plane';
case 0x23 : return 'GameLib.D3.Mesh.Curve';
case 0x24 : return 'GameLib.D3.PhysicsWorld';
case 0x25 : return 'GameLib.D3.Broadphase';
case 0x26 : return 'GameLib.D3.Solver';
case 0x27 : return 'GameLib.D3.RigidBody';
case 0x28 : return 'GameLib.D3.Shape';
case 0x29 : return 'GameLib.D3.Shape.Box';
case 0x2a : return 'GameLib.D3.Shape.Sphere';
case 0x2b : return 'GameLib.D3.Shape.TriMesh';
case 0x2c : return 'GameLib.D3.Shape.ConvexHull';
case 0x2d : return 'GameLib.D3.Shape.ConvexHull.Cylinder';
case 0x2e : return 'GameLib.D3.Shape.HeightMap';
case 0x2f : return 'GameLib.D3.Shape.Plane';
case 0x30 : return 'GameLib.D3.Controls';
case 0x31 : return 'GameLib.D3.Controls.Editor';
case 0x32 : return 'GameLib.D3.Controls.Touch';
case 0x33 : return 'GameLib.D3.FrictionMaterial';
case 0x34 : return 'GameLib.D3.FrictionContactMaterial';
case 0x35 : return 'GameLib.D3.RaycastVehicle';
case 0x36 : return 'GameLib.D3.RaycastWheel';
case 0x37 : return 'GameLib.Clock';
case 0x38 : return 'GameLib.D3.Animation';
case 0x39 : return 'GameLib.D3.Controls.Keyboard';
case 0x3a : return 'GameLib.D3.Controls.Mouse';
case 0x3b : return 'GameLib.D3.Mesh.Text';
case 0x3c : return 'GameLib.D3.Font';
case 0x3d : return 'GameLib.D3.Canvas';
case 0x3e : return 'GameLib.D3.Bone';
case 0x3f : return 'GameLib.D3.Mesh.Box';
case 0x40 : return 'GameLib.D3.Mesh.Cylinder';
case 0x41 : return 'GameLib.D3.System.Animation';
case 0x42 : return 'GameLib.D3.System.CustomCode';
case 0x43 : return 'GameLib.D3.System.GUI';
case 0x44 : return 'GameLib.D3.System.Input';
case 0x45 : return 'GameLib.D3.System.Linking';
case 0x46 : return 'GameLib.D3.System.Physics';
case 0x47 : return 'GameLib.D3.System.Render';
case 0x48 : return 'GameLib.D3.System.Storage';
case 0x49 : return 'GameLib.D3.System.Visualization';
case 0x50 : return 'GameLib.D3.Fog';
case 0x51 : return 'GameLib.D3.Mesh.Line';
case 0x52 : return 'GameLib.D3.ParticleEngine';
case 0x53 : return 'GameLib.D3.System.Particle';
case 0x54 : return 'GameLib.D3.Particle';
case 0x55 : return 'GameLib.D3.Audio';
case 0x56 : return 'GameLib.D3.System.Audio';
break;
}
throw new Error('Unknown component type: ' + number );
};
/**
* Components are linked at runtime - for storing, we just store the ID
* @returns {*}
*/
GameLib.Component.prototype.toApiObject = function() {
return this.id;
};
GameLib.Component.prototype.processComponent = function(object) {
if (object instanceof GameLib.Component) {
object.buildIdToObject();
if (!object.linked) {
this.linked = false;
}
var idToObject = object.idToObject;
for (var objectProperty in idToObject) {
if (idToObject.hasOwnProperty(objectProperty)) {
this.idToObject[objectProperty] = idToObject[objectProperty];
}
}
if (object.id) {
this.idToObject[object.id] = object;
} else {
console.warn('Object with no ID passed: ' + object)
}
} else if (typeof object === 'string') {
this.linked = false;
} else {
console.warn('Unhandled type of object: ', object);
}
};
/**
* This function - builds an 'id to object' object - which contains the ids which point directly
* to its corresponding object, for all the objects contained inside this object
*/
GameLib.Component.prototype.buildIdToObject = function() {
if (this.building) {
return;
}
/**
* If this component 'building' flag is true - it is in the process of building idToObject up the callstack and the
* caller should know to not try to build idToObject again (prevent infinite recursion)
*/
this.building = true;
/**
* If any child component is not fully linked, this component will show as not linked
* @type {boolean}
*/
this.linked = true;
this.idToObject = {};
for (var property in this.linkedObjects) {
if (
this.linkedObjects.hasOwnProperty(property) &&
this.hasOwnProperty(property) &&
this[property] &&
property.indexOf('parent') !== 0
) {
if (this.linkedObjects[property] instanceof Array) {
/**
* Remove null objects (can happen)
*/
this[property] = this[property].filter(
function (object) {
if (object === null) {
console.log('null object found and removed');
return false;
}
return true;
}
);
this[property].map(
function (object) {
this.processComponent(object);
}.bind(this)
);
} else {
this.processComponent(this[property]);
}
}
}
if (this instanceof GameLib.D3.Scene) {
if (!this.storeClones) {
this.clones.map(
function (clone) {
if (this.idToObject.hasOwnProperty(clone.id)) {
delete this.idToObject[clone.id];
}
}.bind(this)
)
}
}
this.idToObject[this.id] = this;
this.building = false;
};
GameLib.Component.prototype.generateNewIds = function() {
this.buildIdToObject();
var codeComponents = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.CustomCode);
for (var property in this.idToObject) {
if (this.idToObject.hasOwnProperty(property)) {
var oldId = this.idToObject[property].id;
var newId = GameLib.Utils.RandomId();
this.idToObject[property].id = newId;
this.idToObject[property].name = this.idToObject[property].name.replace(oldId,newId);
codeComponents.map(function(codeComponent){
codeComponent.code = codeComponent.code.replace(oldId,newId);
});
}
}
};
GameLib.Component.prototype.remove = function() {
this.buildIdToObject();
var dependencies = this.getDependencies();
dependencies.map(
function(objectId) {
var childComponent = this.idToObject[objectId];
if (childComponent instanceof GameLib.Component) {
childComponent.remove();
}
}.bind(this)
);
GameLib.Event.Emit(
GameLib.Event.REMOVE_COMPONENT,
{
component : this
}
)
};
GameLib.Component.prototype.clone = function() {
var apiObject = this.toApiObject();
this.cloneNumber += 1;
apiObject.id = GameLib.Utils.RandomId();
apiObject.name = this.name + ' Clone (' + this.cloneNumber + ')';
var runtimeObject = null;
try {
runtimeObject = new this.constructor(this.graphics, apiObject);
} catch (e){
console.log(e);
try {
runtimeObject = new this.constructor(this.physics, apiObject);
} catch (e) {
console.log(e);
try {
runtimeObject = new this.constructor(this.coder, apiObject);
} catch (e) {
console.log(e);
console.log('failed to construct a runtime component');
return;
}
}
}
runtimeObject.isClone = true;
GameLib.Event.Emit(
GameLib.Event.COMPONENT_CLONED,
{
parent : this,
component : runtimeObject
}
);
runtimeObject.parentEntity = null;
// if (this.parentEntity instanceof GameLib.Entity) {
// this.parentEntity.addComponent(runtimeObject);
// }
return runtimeObject;
};
/**
* Clones only the instance
*/
GameLib.Component.prototype.cloneInstance = function() {
var clone = null;
if (
this.instance &&
this.instance.clone &&
typeof (this.instance.clone === 'function')) {
clone = this.instance.clone();
GameLib.Event.Emit(
GameLib.Event.INSTANCE_CLONED,
{
component : this,
instance : clone
}
)
}
return clone;
};
GameLib.Component.prototype.saveToRemoteAPI = function() {
this.save(true);
};
GameLib.Component.prototype.save = function(remote) {
var toSave = [];
var saved = [];
var failed = [];
this.buildIdToObject();
if (this.saveSubscription || this.saveErrorSubscription) {
console.warn('another save is in progress');
return;
}
GameLib.Event.Emit(
GameLib.Event.SAVING,
{
component: this
}
);
this.saveSubscription = GameLib.Event.Subscribe(
GameLib.Event.COMPONENT_SAVED,
function(data) {
saved.push(data.component);
if (failed.length + saved.length === toSave.length) {
this.saveSubscription.remove();
this.saveSubscription = null;
this.saveErrorSubscription.remove();
this.saveErrorSubscription = null;
GameLib.Event.Emit(
GameLib.Event.DONE_SAVING,
{
failed: failed,
saved: saved
}
)
}
}.bind(this)
);
this.saveErrorSubscription = GameLib.Event.Subscribe(
GameLib.Event.SAVE_COMPONENT_ERROR,
function(data) {
failed.push(data.component);
if (failed.length + saved.length === toSave.length) {
this.saveSubscription.remove();
this.saveSubscription = null;
this.saveErrorSubscription.remove();
this.saveErrorSubscription = null;
GameLib.Event.Emit(
GameLib.Event.DONE_SAVING,
{
failed: failed,
saved: saved
}
)
}
}.bind(this)
);
for (var property in this.idToObject) {
if (
this.idToObject.hasOwnProperty(property) &&
this.idToObject[property] instanceof GameLib.Component
) {
var apiObject = this.idToObject[property].toApiObject();
apiObject.componentType = this.idToObject[property].componentType;
toSave.push(apiObject);
this.publish(
GameLib.Event.SAVE_COMPONENT,
{
apiObject: apiObject,
remote: remote
}
);
}
}
};
/**
* Raw Clock API object - should always correspond with the Clock Schema
* @constructor
* @param id
* @param name
* @param parentEntity
*/
GameLib.API.Clock = function(
id,
name,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Clock (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.API.Clock.prototype = Object.create(GameLib.Component.prototype);
GameLib.API.Clock.prototype.constructor = GameLib.API.Clock;
/**
* Creates an API camera from an Object camera
* @param objectClock
* @constructor
*/
GameLib.API.Clock.FromObject = function(objectClock) {
return new GameLib.API.Clock(
objectClock.id,
objectClock.name,
objectClock.parentEntity
);
};
/**
* API Color
* @param r
* @param g
* @param b
* @param a
* @constructor
*/
GameLib.API.Color = function (r, g, b, a) {
if (GameLib.Utils.UndefinedOrNull(r)) {
r = 1;
}
this.r = r;
if (GameLib.Utils.UndefinedOrNull(g)) {
g = 1;
}
this.g = g;
if (GameLib.Utils.UndefinedOrNull(b)) {
b = 1;
}
this.b = b;
if (GameLib.Utils.UndefinedOrNull(a)) {
a = 0;
}
this.a = a;
};
/**
* Returns an API color from an Object color
* @param objectColor
* @constructor
*/
GameLib.API.Color.FromObject = function(objectColor) {
if (GameLib.Utils.UndefinedOrNull(objectColor)){
objectColor = {};
}
return new GameLib.API.Color(
objectColor.r,
objectColor.g,
objectColor.b,
objectColor.a
);
};
/**
* Converts the current color to HTML hex format (ex. #ffffff)
* @returns {string}
*/
GameLib.API.Color.prototype.toHex = function() {
if (this.r < 0) {
this.r = 0;
}
if (this.g < 0) {
this.g = 0;
}
if (this.b < 0) {
this.b = 0;
}
if (this.r > 1) {
this.r = 1;
}
if (this.g > 1) {
this.g = 1;
}
if (this.b > 1) {
this.b = 1;
}
var rf = Math.floor(this.r >= 1? 255 : this.r * 256.0).toString(16);
var gf = Math.floor(this.g >= 1? 255 : this.g * 256.0).toString(16);
var bf = Math.floor(this.b >= 1? 255 : this.b * 256.0).toString(16);
if (rf.length < 2) {
rf = '0' + rf;
}
if (gf.length < 2) {
gf = '0' + gf;
}
if (bf.length < 2) {
bf = '0' + bf;
}
return '#' + rf + gf + bf;
};
/**
* Sets this object color to what the hex value is
* @param hex
* @returns {string}
*/
GameLib.API.Color.prototype.fromHex = function(hex) {
var matches = hex.match(new RegExp('#+(..)(..)(..)'));
this.r = parseInt(matches[1], 16) / 255.0;
this.g = parseInt(matches[2], 16) / 255.0;
this.b = parseInt(matches[3], 16) / 255.0;
};
/**
* API DomElement
* @param id
* @param name
* @param domElementId
* @param parentEntity
* @constructor
*/
GameLib.API.DomElement = function(
id,
name,
domElementId,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'DOM Element (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(domElementId)) {
domElementId = '';
}
this.domElementId = domElementId;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.API.DomElement.prototype = Object.create(GameLib.Component.prototype);
GameLib.API.DomElement.prototype.constructor = GameLib.API.DomElement;
/**
* Returns an API domElement from an Object domElement
* @param objectDomElement
* @constructor
*/
GameLib.API.DomElement.FromObject = function (objectDomElement) {
return new GameLib.API.DomElement(
objectDomElement.id,
objectDomElement.name,
objectDomElement.domElementId,
objectDomElement.parentEntity
)
};
/**
* Entity API Object (for storing / loading entities to and from API)
* @constructor
* @param id
* @param name
* @param entities GameLib.API.Entity[]
* @param defaultEntity
* @param defaultRenderer
*/
GameLib.API.EntityManager = function(
id,
name,
entities,
defaultEntity,
defaultRenderer
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Entity Manager (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(entities)) {
entities = [];
}
this.entities = entities;
if (GameLib.Utils.UndefinedOrNull(defaultEntity)) {
defaultEntity = null;
}
this.defaultEntity = defaultEntity;
if (GameLib.Utils.UndefinedOrNull(defaultRenderer)) {
defaultRenderer = null;
}
this.defaultRenderer = defaultRenderer;
};
GameLib.API.EntityManager.prototype = Object.create(GameLib.Component.prototype);
GameLib.API.EntityManager.prototype.constructor = GameLib.API.EntityManager;
/**
* Creates an API entity manager from an Object entity manager
* @param objectEntityManager
* @constructor
*/
GameLib.API.EntityManager.FromObject = function(objectEntityManager) {
var apiEntities = objectEntityManager.entities.map(
function (objectEntity) {
return GameLib.API.Entity.FromObject(objectEntity);
}
);
return new GameLib.API.EntityManager(
objectEntityManager.id,
objectEntityManager.name,
apiEntities,
objectEntityManager.defaultEntity,
objectEntityManager.defaultRenderer
);
};
/**
* Entity API Object (for storing / loading entities to and from API)
* @param id
* @param name
* @param components GameLib.Component[]
* @param parentEntity GameLib.Entity
* @param parentEntityManager
* @constructor
*/
GameLib.API.Entity = function(
id,
name,
components,
parentEntity,
parentEntityManager
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Entity (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(components)) {
components = [];
}
this.components = components;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.Utils.UndefinedOrNull(parentEntityManager)) {
parentEntityManager = null;
}
this.parentEntityManager = parentEntityManager;
this.activeComponent = null;
};
GameLib.API.Entity.prototype = Object.create(GameLib.Component.prototype);
GameLib.API.Entity.prototype.constructor = GameLib.API.Entity;
/**
* Returns an API entity from an Object entity
* @param objectEntity
* @constructor
*/
GameLib.API.Entity.FromObject = function(objectEntity) {
return new GameLib.API.Entity(
objectEntity.id,
objectEntity.name,
objectEntity.components,
objectEntity.parentEntity,
objectEntity.parentEntityManager
)
};
/**
* Api Matrix 4
* @param row0 GameLib.API.Vector4
* @param row1 GameLib.API.Vector4
* @param row2 GameLib.API.Vector4
* @param row3 GameLib.API.Vector4
* @constructor
*/
GameLib.API.Matrix4 = function ApiMatrix4(
row0,
row1,
row2,
row3
) {
this.rows = [];
if (GameLib.Utils.UndefinedOrNull(row0)) {
row0 = new GameLib.API.Vector4(1, 0, 0, 0);
}
this.rows[0] = row0;
if (GameLib.Utils.UndefinedOrNull(row1)) {
row1 = new GameLib.API.Vector4(0, 1, 0, 0);
}
this.rows[1] = row1;
if (GameLib.Utils.UndefinedOrNull(row2)) {
row2 = new GameLib.API.Vector4(0, 0, 1, 0);
}
this.rows[2] = row2;
if (GameLib.Utils.UndefinedOrNull(row3)) {
row3 = new GameLib.API.Vector4(0, 0, 0, 1);
}
this.rows[3] = row3;
this.temp = [];
this.temp.push(
new GameLib.API.Vector4()
);
this.temp.push(
new GameLib.API.Vector4()
);
this.temp.push(
new GameLib.API.Vector4()
);
this.temp.push(
new GameLib.API.Vector4()
);
this.forward = new GameLib.API.Vector4();
this.left = new GameLib.API.Vector4();
this.up = new GameLib.API.Vector4();
};
/**
* Returns an API matrix from an Object matrix
* @param objectMatrix
* @constructor
*/
GameLib.API.Matrix4.FromObject = function(objectMatrix) {
if (objectMatrix.rows) {
return new GameLib.API.Matrix4(
GameLib.API.Vector4.FromObject(objectMatrix.rows[0]),
GameLib.API.Vector4.FromObject(objectMatrix.rows[1]),
GameLib.API.Vector4.FromObject(objectMatrix.rows[2]),
GameLib.API.Vector4.FromObject(objectMatrix.rows[3])
);
} else if (objectMatrix instanceof Array) {
return new GameLib.API.Matrix4(
GameLib.API.Vector4.FromObject(objectMatrix[0]),
GameLib.API.Vector4.FromObject(objectMatrix[1]),
GameLib.API.Vector4.FromObject(objectMatrix[2]),
GameLib.API.Vector4.FromObject(objectMatrix[3])
);
} else {
console.warn('Unsupported object matrix type - whats your DB version?');
throw new Error('Unsupported object matrix type - whats your DB version?');
}
};
GameLib.API.Matrix4.prototype.rotationMatrixX = function (radians) {
this.identity();
this.rows[1] = new GameLib.API.Vector4(0, Math.cos(radians), -1 * Math.sin(radians), 0);
this.rows[2] = new GameLib.API.Vector4(0, Math.sin(radians), Math.cos(radians), 0);
return this;
};
GameLib.API.Matrix4.prototype.rotationMatrixY = function (radians) {
this.identity();
this.rows[0] = new GameLib.API.Vector4(
Math.cos(radians),
0,
Math.sin(radians),
0
);
this.rows[2] = new GameLib.API.Vector4(
-1 * Math.sin(radians),
0,
Math.cos(radians),
0
);
return this;
};
GameLib.API.Matrix4.prototype.rotationMatrixZ = function (radians) {
this.identity();
this.rows[0] = new GameLib.API.Vector4(Math.cos(radians), -1 * Math.sin(radians), 0, 0);
this.rows[1] = new GameLib.API.Vector4(Math.sin(radians), Math.cos(radians), 0, 0);
return this;
};
GameLib.API.Matrix4.prototype.rotateX = function (radians, point) {
this.identity();
this.rotationMatrixX(radians);
return this.multiply(point);
};
GameLib.API.Matrix4.prototype.rotateY = function (radians, point) {
this.identity();
this.rotationMatrixY(radians);
return this.multiply(point);
};
GameLib.API.Matrix4.prototype.rotateZ = function (radians, point) {
this.identity();
this.rotationMatrixZ(radians);
return this.multiply(point);
};
GameLib.API.Matrix4.prototype.multiply = function (mvp) {
if (mvp instanceof GameLib.API.Quaternion || mvp instanceof GameLib.API.Vector4) {
return new GameLib.API.Quaternion(
this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z + this.rows[0].w * mvp.w,
this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z + this.rows[1].w * mvp.w,
this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z + this.rows[2].w * mvp.w,
this.rows[3].x * mvp.x + this.rows[3].y * mvp.y + this.rows[3].z * mvp.z + this.rows[3].w * mvp.w
);
} else if (mvp instanceof GameLib.API.Vector3) {
return new GameLib.API.Vector3(
this.rows[0].x * mvp.x + this.rows[0].y * mvp.y + this.rows[0].z * mvp.z,
this.rows[1].x * mvp.x + this.rows[1].y * mvp.y + this.rows[1].z * mvp.z,
this.rows[2].x * mvp.x + this.rows[2].y * mvp.y + this.rows[2].z * mvp.z
);
}
};
GameLib.API.Matrix4.prototype.identity = function () {
this.rows = [
new GameLib.API.Vector4(1, 0, 0, 0),
new GameLib.API.Vector4(0, 1, 0, 0),
new GameLib.API.Vector4(0, 0, 1, 0),
new GameLib.API.Vector4(0, 0, 0, 1)
];
};
/**
* API Mouse
* @param id
* @param name
* @param x
* @param y
* @param parentEntity
* @constructor
*/
GameLib.API.Mouse = function(
id,
name,
x,
y,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Mouse (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
};
GameLib.API.Mouse.prototype = Object.create(GameLib.Component.prototype);
GameLib.API.Mouse.prototype.constructor = GameLib.API.Mouse;
/**
* Returns an API mouse from an Object mouse
* @param objectMouse
* @constructor
*/
GameLib.API.Mouse.FromObject = function (objectMouse) {
return new GameLib.API.Mouse(
objectMouse.id,
objectMouse.name,
objectMouse.x,
objectMouse.y,
objectMouse.parentEntity
)
};
/**
* Quaternion
* @param x
* @param y
* @param z
* @param w
* @param axis
* @param angle
* @constructor
*/
GameLib.API.Quaternion = function (
x,
y,
z,
w,
axis,
angle
) {
if (GameLib.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
if (GameLib.Utils.UndefinedOrNull(z)) {
z = 0;
}
this.z = z;
if (GameLib.Utils.UndefinedOrNull(w)) {
w = 1;
}
this.w = w;
if (GameLib.Utils.UndefinedOrNull(axis)) {
axis = new GameLib.API.Vector3();
}
this.axis = axis;
if (GameLib.Utils.UndefinedOrNull(angle)) {
angle = 0;
}
this.angle = angle;
};
GameLib.API.Quaternion.prototype.translate = function (v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
};
GameLib.API.Quaternion.prototype.copy = function () {
return new GameLib.API.Quaternion(
this.x,
this.y,
this.z,
this.w
);
};
/**
* Note, this normalize function leaves 'w' component untouched
*/
GameLib.API.Quaternion.prototype.normalize = function () {
var EPSILON = 0.000001;
var v2 = this.x * this.x + this.y * this.y + this.z * this.z;
if (v2 < EPSILON) {
return this; //do nothing for zero vector
}
var invLength = 1 / Math.sqrt(v2);
this.x *= invLength;
this.y *= invLength;
this.z *= invLength;
};
GameLib.API.Quaternion.prototype.multiply = function (q) {
var x, y, z, w;
var a = q;
var b = this;
if (q instanceof GameLib.API.Matrix4) {
x = a.rows[0].x * b.x + a.rows[0].y * b.y + a.rows[0].z * b.z + a.rows[0].w * b.w;
y = a.rows[1].x * b.x + a.rows[1].y * b.y + a.rows[1].z * b.z + a.rows[1].w * b.w;
z = a.rows[2].x * b.x + a.rows[2].y * b.y + a.rows[2].z * b.z + a.rows[2].w * b.w;
w = a.rows[3].x * b.x + a.rows[3].y * b.y + a.rows[3].z * b.z + a.rows[3].w * b.w;
this.x = x;
this.y = y;
this.z = z;
this.w = w;
return this;
} else if (q instanceof GameLib.API.Quaternion) {
x = ((a.x * b.x) - (a.y * b.y) - (a.z * b.z) - (a.w * a.w));
y = ((a.x * b.y) + (a.y * b.x) - (a.z * b.w) + (a.w * a.z));
z = ((a.x * b.z) + (a.y * b.w) + (a.z * b.x) - (a.w * a.y));
w = ((a.x * b.w) - (a.y * b.z) + (a.z * b.y) + (a.w * a.x));
this.x = x;
this.y = y;
this.z = z;
this.w = w;
return this;
} else {
console.log("This functionality not implemented - please do this");
throw new Error("This functionality not implemented - please do this");
}
};
GameLib.API.Quaternion.prototype.setFromAngle = function (angle) {
this.instance.setFromAxisAngle(this.axis.instance, angle);
this.x = this.instance.x;
this.y = this.instance.y;
this.z = this.instance.z;
this.w = this.instance.w;
return this;
};
GameLib.API.Quaternion.prototype.subtract = function (v) {
if (v instanceof GameLib.API.Vector3) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
}
if (v instanceof GameLib.API.Quaternion) {
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
this.w -= v.w;
}
return this;
};
GameLib.API.Quaternion.prototype.magnitude = function () {
return Math.sqrt(
(this.x * this.x) +
(this.y * this.y) +
(this.z * this.z) +
(this.w * this.w)
);
};
GameLib.API.Quaternion.prototype.normalize = function () {
var magnitude = this.magnitude();
if (magnitude < 0.000001) {
return this; //do nothing for zero vector
}
this.x *= magnitude;
this.y *= magnitude;
this.z *= magnitude;
this.w *= magnitude;
return this;
};
/**
*
* @param matrix4 GameLib.Matrix4
*/
GameLib.API.Quaternion.prototype.setFromRotationMatrix = function(matrix4) {
this.instance.setFromRotationMatrix(matrix4.instance);
this.x = this.instance.x;
this.y = this.instance.y;
this.z = this.instance.z;
this.w = this.instance.w;
};
/**
*
* @param quaternion GameLib.Quaternion
* @param t
* @returns {GameLib.Quaternion}
*/
GameLib.API.Quaternion.prototype.slerp = function (quaternion, t) {
this.updateInstance();
this.instance.slerp(quaternion.instance, t);
this.x = this.instance.x;
this.y = this.instance.y;
this.z = this.instance.z;
this.w = this.instance.w;
return this;
};
/**
* Returns an API quaternion from an Object quaternion
* @param objectQuaternion
* @constructor
*/
GameLib.API.Quaternion.FromObject = function (objectQuaternion) {
var apiAxis = null;
if (objectQuaternion.axis) {
apiAxis = GameLib.API.Vector3.FromObject(objectQuaternion.axis);
}
return new GameLib.API.Quaternion(
objectQuaternion.x,
objectQuaternion.y,
objectQuaternion.z,
objectQuaternion.w,
apiAxis,
objectQuaternion.angle
)
};
GameLib.API.Quaternion.Points = function () {
this.vectors = [];
};
GameLib.API.Quaternion.Points.prototype.add = function (vector) {
if (vector instanceof GameLib.API.Vector3) {
vector = new GameLib.API.Quaternion(
vector.x,
vector.y,
vector.z,
1
)
}
if (!vector instanceof GameLib.API.Quaternion) {
console.warn("Vector needs to be of type Quaternion");
throw new Error("Vector needs to be of type Quaternion");
}
this.vectors.push(vector);
return this;
};
GameLib.API.Quaternion.Points.prototype.copy = function () {
var vectors = [];
for (var i = 0; i < this.vectors.length; i++) {
vectors.push(this.vectors[i].copy());
}
return vectors;
};
GameLib.API.Quaternion.Points.prototype.maximizeXDistance = function (grain) {
// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
var multiplier = 0;
var rotationMatrixY = new GameLib.API.Matrix4().rotationMatrixY(grain);
var totalRadians = 0;
var backupVectors = this.copy();
var maxXDistance = 0;
for (var i = 0; i < Math.PI * 2; i += grain) {
multiplier++;
for (var j = 0; j < this.vectors.length; j++) {
this.vectors[j] = rotationMatrixY.multiply(this.vectors[j]);
}
var distances = this.distances();
if (distances.x > maxXDistance) {
maxXDistance = distances.x;
totalRadians = multiplier * grain;
}
}
this.vectors = backupVectors;
// console.log("distance: " + maxXDistance + " radians : " + totalRadians);
var maxRotationMatrix = new GameLib.API.Matrix4().rotationMatrixY(totalRadians);
for (var k = 0; k < this.vectors.length; k++) {
this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
}
// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
};
GameLib.API.Quaternion.Points.prototype.maximizeYDistance = function (grain) {
// console.log("vectors (before): " + JSON.stringify(this.vectors, null, 2));
var multiplier = 0;
var rotationMatrixX = new GameLib.API.Matrix4().rotationMatrixX(grain);
var totalRadians = 0;
var backupVectors = this.copy();
var maxYDistance = 0;
for (var i = 0; i < Math.PI * 2; i += grain) {
multiplier++;
for (var j = 0; j < this.vectors.length; j++) {
this.vectors[j] = rotationMatrixX.multiply(this.vectors[j]);
}
var distances = this.distances();
if (distances.y > maxYDistance) {
maxYDistance = distances.y;
totalRadians = multiplier * grain;
}
}
this.vectors = backupVectors;
// console.log("distance: " + maxYDistance + " radians : " + totalRadians);
var maxRotationMatrix = new GameLib.API.Matrix4().rotationMatrixX(totalRadians);
for (var k = 0; k < this.vectors.length; k++) {
this.vectors[k] = maxRotationMatrix.multiply(this.vectors[k]);
}
// console.log("vectors (after): " + JSON.stringify(this.vectors, null, 2));
};
GameLib.API.Quaternion.Points.prototype.lookAt = function (at, up) {
var polyCenter = this.average();
console.log("poly center : " + JSON.stringify(polyCenter));
var lookAtMatrix = new GameLib.API.Matrix4().lookAt(polyCenter, at, up);
lookAtMatrix.rows[0] = new GameLib.API.Quaternion(1, 0, 0, 0);
lookAtMatrix.rows[1] = new GameLib.API.Quaternion(0, 0, 1, 0);
lookAtMatrix.rows[2] = new GameLib.API.Quaternion(0, 1, 0, 0);
console.log("look at matrix : " + JSON.stringify(lookAtMatrix, null, 2));
for (var i = 0; i < this.vectors.length; i++) {
console.log("vector " + i + " (before): " + JSON.stringify(this.vectors[i]));
this.vectors[i] = lookAtMatrix.multiply(this.vectors[i]);
console.log("vector " + i + " (after) : " + JSON.stringify(this.vectors[i]));
}
};
GameLib.API.Quaternion.Points.prototype.distances = function () {
var minX = this.vectors[0].x;
var minY = this.vectors[0].y;
var minZ = this.vectors[0].z;
var maxX = this.vectors[0].x;
var maxY = this.vectors[0].y;
var maxZ = this.vectors[0].z;
for (var i = 0; i < this.vectors.length; i++) {
if (this.vectors[i].x < minX) {
minX = this.vectors[i].x;
}
if (this.vectors[i].y < minY) {
minY = this.vectors[i].y;
}
if (this.vectors[i].z < minZ) {
minZ = this.vectors[i].z;
}
if (this.vectors[i].x > maxX) {
maxX = this.vectors[i].x;
}
if (this.vectors[i].y > maxY) {
maxY = this.vectors[i].y;
}
if (this.vectors[i].z > maxZ) {
maxZ = this.vectors[i].z;
}
}
return new GameLib.API.Vector3(
Math.abs(maxX - minX),
Math.abs(maxY - minY),
Math.abs(maxY - minZ)
)
};
GameLib.API.Quaternion.Points.prototype.average = function () {
var averageX = 0;
var averageY = 0;
var averageZ = 0;
for (var i = 0; i < this.vectors.length; i++) {
averageX += this.vectors[i].x;
averageY += this.vectors[i].y;
averageZ += this.vectors[i].z;
}
return new GameLib.API.Vector3(
averageX / this.vectors.length,
averageY / this.vectors.length,
averageZ / this.vectors.length
);
};
GameLib.API.Quaternion.Points.prototype.negate = function () {
for (var i = 0; i < this.vectors.length; i++) {
this.vectors[i].x *= -1;
this.vectors[i].y *= -1;
this.vectors[i].z *= -1;
}
return this;
};
GameLib.API.Quaternion.Points.prototype.toOrigin = function () {
var distanceFromOrigin = this.average().negate();
for (var i = 0; i < this.vectors.length; i++) {
this.vectors[i].translate(distanceFromOrigin);
}
};
/**
* This component renders a scene
* @param id String
* @param name String
* @param systemType
* @param parentEntity
* @constructor
*/
GameLib.API.System = function (
id,
name,
systemType,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = "System (" + this.id + ")";
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(systemType)) {
systemType = GameLib.System.SYSTEM_TYPE_RENDER;
}
this.systemType = systemType;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.API.System.prototype = Object.create(GameLib.Component.prototype);
GameLib.API.System.prototype.constructor = GameLib.API.System;
/**
* Object to GameLib.D3.API.System
* @param objectComponent
* @constructor
*/
GameLib.API.System.FromObject = function(objectComponent) {
return new GameLib.API.System(
objectComponent.id,
objectComponent.name,
objectComponent.systemType,
objectComponent.parentEntity
);
};
GameLib.API.Vector2 = function (x, y) {
if (GameLib.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
};
GameLib.API.Vector2.prototype.copy = function () {
return new GameLib.API.Vector2(
this.x,
this.y
);
};
GameLib.API.Vector2.prototype.equals = function (v) {
return this.x === v.x && this.y === v.y;
};
/**
* Returns an API vector from an Object vector
* @param objectVector
* @constructor
*/
GameLib.API.Vector2.FromObject = function (objectVector) {
return new GameLib.API.Vector2(
objectVector.x,
objectVector.y
)
};
GameLib.API.Vector3 = function (x, y, z) {
if (GameLib.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
if (GameLib.Utils.UndefinedOrNull(z)) {
z = 0;
}
this.z = z;
};
GameLib.API.Vector3.prototype.negate = function() {
this.x = -this.x;
this.y = -this.y;
this.z = -this.z;
return this;
};
GameLib.API.Vector3.prototype.subtract = function (v) {
return new GameLib.API.Vector3(
this.x - v.x,
this.y - v.y,
this.z - v.z
);
};
GameLib.API.Vector3.prototype.sub = function (v) {
return new GameLib.API.Vector3(
this.x - v.x,
this.y - v.y,
this.z - v.z
);
};
GameLib.API.Vector3.prototype.equals = function (v) {
return this.x === v.x && this.y === v.y && this.z === v.z;
};
GameLib.API.Vector3.prototype.cross = function (v) {
return new GameLib.API.Vector3(
this.y * v.z - this.z * v.y,
this.z * v.x - this.x * v.z,
this.x * v.y - this.y * v.x
);
};
GameLib.API.Vector3.clockwise = function (u, v, w, viewPoint) {
var normal = GameLib.API.Vector3.normal(u, v, w);
var uv = u.copy();
var winding = normal.dot(uv.subtract(viewPoint));
return (winding > 0);
};
GameLib.API.Vector3.normal = function (u, v, w) {
var vv = v.copy();
var wv = w.copy();
return vv.subtract(u).cross(wv.subtract(u));
};
GameLib.API.Vector3.prototype.lookAt = function (at, up) {
var lookAtMatrix = GameLib.API.Matrix4.lookAt(this, at, up);
return this.multiply(lookAtMatrix);
};
GameLib.API.Vector3.prototype.translate = function (v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
};
GameLib.API.Vector3.prototype.add = function (v) {
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
};
GameLib.API.Vector3.prototype.squared = function () {
return this.x * this.x + this.y * this.y + this.z * this.z;
};
GameLib.API.Vector3.prototype.copy = function () {
return new GameLib.API.Vector3(
this.x,
this.y,
this.z
);
};
GameLib.API.Vector3.prototype.set = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
GameLib.API.Vector3.prototype.lerp = function ( v, alpha ) {
return new GameLib.API.Vector3(
this.x + ( v.x - this.x ) * alpha,
this.y + ( v.y - this.y ) * alpha,
this.z + ( v.z - this.z ) * alpha
);
};
GameLib.API.Vector3.prototype.distanceTo = function(v) {
var dx = this.x - v.x,
dy = this.y - v.y,
dz = this.z - v.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
};
/**
* @return {number}
*/
GameLib.API.Vector3.AngleDirection = function(forward, directionToCheck, up) {
var perp = forward.cross(directionToCheck);
var dir = perp.dot(up);
if (dir > 0.0) {
return 1.0;
} else if (dir < 0.0) {
return -1.0;
} else {
return 0.0;
}
};
/**
* Multiplies this vector with a scalar, vector or matrix. If you want a copy, copy() it first
* @param object {Number | GameLib.API.Vector3 | GameLib.API.Vector4 | GameLib.API.Matrix3 | GameLib.API.Matrix4}
* @param cross boolean true if you want the cross product, otherwise returns the scalar (dot or inner) product
* @returns {GameLib.API.Vector3 | Number}
*/
GameLib.API.Vector3.prototype.multiply = function (object, cross) {
var x, y, z;
var a = object;
var b = this;
if (GameLib.Utils.UndefinedOrNull(cross)) {
cross = false;
}
if (typeof object === 'number') {
if (cross) {
this.x *= object;
this.y *= object;
this.z *= object;
return this;
} else {
return ((this.x * object) + (this.y * object) + (this.z * object));
}
}
if (object instanceof GameLib.API.Vector3) {
if (cross) {
x = (a.y * b.z) - (a.z * b.y);
y = (a.z * b.x) - (a.x * b.z);
z = (a.x * b.y) - (a.y * b.x);
this.x = x;
this.y = y;
this.z = z;
return this;
} else {
return ((this.x * object.x) + (this.y * object.y) + (this.z * object.z));
}
} else {
console.log("functionality not implemented - please do this");
throw new Error("not implemented");
}
};
GameLib.API.Vector3.prototype.dot = function (v) {
return (this.x * v.x) + (this.y * v.y) + (this.z * v.z);
};
GameLib.API.Vector3.prototype.normalize = function () {
var EPSILON = 0.000001;
var v2 = this.squared();
if (v2 < EPSILON) {
return this; //do nothing for zero vector
}
var invLength = 1.0 / Math.sqrt(v2);
return new GameLib.API.Vector3(
this.x * invLength,
this.y * invLength,
this.z * invLength
);
};
GameLib.API.Vector3.prototype.clone = function () {
return new GameLib.API.Vector3(
this.x,
this.y,
this.z
);
};
GameLib.API.Vector3.prototype.applyQuaternion = function(q) {
var x = this.x, y = this.y, z = this.z;
var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
// calculate quat * vector
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = - qx * x - qy * y - qz * z;
// calculate result * inverse quat
this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
return this;
};
GameLib.API.Vector3.prototype.clamp = function(min, max) {
this.x = Math.max( min.x, Math.min( max.x, this.x ) );
this.y = Math.max( min.y, Math.min( max.y, this.y ) );
this.z = Math.max( min.z, Math.min( max.z, this.z ) );
return this;
};
GameLib.API.Vector3.prototype.length = function() {
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
};
GameLib.API.Vector3.prototype.reflect = function(normal) {
return this.sub( v1.copy( normal ).multiply( 2 * this.dot( normal ) ) );
};
GameLib.API.Vector3.prototype.angleTo = function (v) {
var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
return Math.acos( exports.Math.clamp( theta, - 1, 1 ) );
};
/**
* Returns an API vector from an Object vector
* @param objectVector
* @constructor
*/
GameLib.API.Vector3.FromObject = function (objectVector) {
return new GameLib.API.Vector3(
objectVector.x,
objectVector.y,
objectVector.z
)
};
GameLib.API.Vector4 = function (x, y, z, w) {
if (GameLib.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
if (GameLib.Utils.UndefinedOrNull(z)) {
z = 0;
}
this.z = z;
if (GameLib.Utils.UndefinedOrNull(w)) {
w = 1;
}
this.w = w;
};
GameLib.API.Vector4.prototype.equals = function (v) {
return this.x === v.x && this.y === v.y && this.z === v.z && this.w === v.w;
};
/**
* Returns an API vector from an Object vector
* @param objectVector
* @constructor
*/
GameLib.API.Vector4.FromObject = function (objectVector) {
return new GameLib.API.Vector4(
objectVector.x,
objectVector.y,
objectVector.z,
objectVector.w
)
};
/**
* Creates a camera object
* @param implementation
* @param apiClock GameLib.API.Clock
* @constructor
*/
GameLib.Clock = function(
implementation,
apiClock
) {
this.implementation = implementation;
this.implementation.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiClock)) {
apiClock = {};
}
if (apiClock instanceof GameLib.Clock) {
return apiClock;
}
GameLib.API.Clock.call(
this,
apiClock.id,
apiClock.name,
apiClock.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_CLOCK
);
} ;
GameLib.Clock.prototype = Object.create(GameLib.API.Clock.prototype);
GameLib.Clock.prototype.constructor = GameLib.Clock;
/**
* Creates a camera instance of 'graphics' type (only THREE for now)
* @returns {THREE.Clock}
*/
GameLib.Clock.prototype.createInstance = function() {
this.instance = new THREE.Clock();
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.Clock.prototype.updateInstance = function() {
};
GameLib.Clock.prototype.getDelta = function() {
var delta = this.instance.getDelta();
/**
* clamp the delta to 1/60
*/
if (delta > (1 / 30.0)) {
// console.log('clipped ' + (delta - (1/30.0)) + ' seconds - essentially lost time');
delta = (1 / 30.0);
}
return delta;
};
/**
* Converts a GameLib.Clock to a new GameLib.API.Clock
* @returns {GameLib.API.Clock}
*/
GameLib.Clock.prototype.toApiObject = function() {
return new GameLib.API.Clock(
this.id,
this.name,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts from an Object camera to a GameLib.Clock
* @param graphics GameLib.Graphics
* @param objectClock Object
* @returns {GameLib.Clock}
* @constructor
*/
GameLib.Clock.FromObject = function(graphics, objectClock) {
var apiClock = GameLib.API.Clock.FromObject(objectClock);
return new GameLib.Clock(
graphics,
apiClock
);
};
/**
* Runtime color for updating instance objects
* @param graphics GameLib.D3.Graphics
* @param parentObject GameLib.D3.*
* @param apiColor GameLib.API.Color
* @param grain Number
* @constructor
*/
GameLib.Color = function (
graphics,
apiColor,
parentObject,
grain
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiColor)) {
apiColor = {};
}
if (apiColor instanceof GameLib.Color) {
return apiColor;
}
GameLib.API.Color.call(
this,
apiColor.r,
apiColor.g,
apiColor.b,
apiColor.a
);
if (GameLib.Utils.UndefinedOrNull(parentObject)) {
parentObject = null;
}
this.parentObject = parentObject;
if (GameLib.Utils.UndefinedOrNull(grain)) {
grain = 0.001;
}
this.grain = grain;
this.createInstance();
};
GameLib.Color.prototype = Object.create(GameLib.API.Color.prototype);
GameLib.Color.prototype.constructor = GameLib.Color;
/**
* Creates an instance color
* @returns {*}
*/
GameLib.Color.prototype.createInstance = function() {
this.instance = new THREE.Color(
this.r,
this.g,
this.b
);
};
/**
* Updates the instance color, calls updateInstance on the parent object
*/
GameLib.Color.prototype.updateInstance = function(property) {
this.instance.r = this.r;
this.instance.g = this.g;
this.instance.b = this.b;
if (this.parentObject &&
this.parentObject.updateInstance) {
this.parentObject.updateInstance(property);
}
};
/**
* Converts runtime color to API Color
* @returns {GameLib.API.Color}
*/
GameLib.Color.prototype.toApiObject = function() {
return new GameLib.API.Color(
this.r,
this.g,
this.b,
this.a
);
};
/**
* Animation Component
* @param id
* @param name
* @param rotationSpeed
* @param translationSpeed
* @param scaleSpeed
* @param rotationFn
* @param translationFn
* @param scaleFn
* @param blocking
* @param applyToMeshWhenDone
* @param meshes
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Animation = function (
id,
name,
rotationSpeed,
translationSpeed,
scaleSpeed,
rotationFn,
translationFn,
scaleFn,
blocking,
applyToMeshWhenDone,
meshes,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Animation (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(rotationSpeed)) {
rotationSpeed = 0;
}
this.rotationSpeed = rotationSpeed;
if (GameLib.Utils.UndefinedOrNull(translationSpeed)) {
translationSpeed = 0;
}
this.translationSpeed = translationSpeed;
if (GameLib.Utils.UndefinedOrNull(scaleSpeed)) {
scaleSpeed = 0;
}
this.scaleSpeed = scaleSpeed;
if (GameLib.Utils.UndefinedOrNull(rotationFn)) {
rotationFn = null;
}
this.rotationFn = rotationFn;
if (GameLib.Utils.UndefinedOrNull(translationFn)) {
translationFn = null;
}
this.translationFn = translationFn;
if (GameLib.Utils.UndefinedOrNull(scaleFn)) {
scaleFn = null;
}
this.scaleFn = scaleFn;
if (GameLib.Utils.UndefinedOrNull(blocking)) {
blocking = {
position : false, //positions can be blocked from accumulating and executing at once
rotation : true, //rotations need to execute in order
scale : false //scale can accumulate
};
}
this.blocking = blocking;
if (GameLib.Utils.UndefinedOrNull(applyToMeshWhenDone)) {
applyToMeshWhenDone = true;
}
this.applyToMeshWhenDone = applyToMeshWhenDone;
if (GameLib.Utils.UndefinedOrNull(meshes)) {
meshes = [];
}
this.meshes = meshes;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Animation.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Animation.prototype.constructor = GameLib.D3.API.Animation;
/**
* Object to GameLib.D3.API.Animation
* @param objectComponent
* @returns {GameLib.D3.API.Animation}
* @constructor
*/
GameLib.D3.API.Animation.FromObject = function(objectComponent) {
return new GameLib.D3.API.Animation(
objectComponent.id,
objectComponent.name,
objectComponent.rotationSpeed,
objectComponent.translationSpeed,
objectComponent.scaleSpeed,
objectComponent.rotationFn,
objectComponent.translationFn,
objectComponent.scaleFn,
objectComponent.blocking,
objectComponent.applyToMeshWhenDone,
objectComponent.meshes,
objectComponent.parentEntity
);
};
/**
* Raw Audio API object - should always correspond with the Audio Schema
* @param id
* @param name
* @param path
* @param loop
* @param volume
* @param camera
* @param overplay
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Audio = function(
id,
name,
path,
loop,
volume,
camera,
overplay,
paused,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Audio (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(path)) {
path = '';
}
this.path = path;
if (GameLib.Utils.UndefinedOrNull(loop)) {
loop = false;
}
this.loop = loop;
if (GameLib.Utils.UndefinedOrNull(volume)) {
volume = 0.5;
}
this.volume = volume;
if (GameLib.Utils.UndefinedOrNull(camera)) {
camera = null;
}
this.camera = camera;
if (GameLib.Utils.UndefinedOrNull(overplay)) {
overplay = false;
}
this.overplay = overplay;
if (GameLib.Utils.UndefinedOrNull(paused)) {
paused = false;
}
this.paused = paused;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Audio.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Audio.prototype.constructor = GameLib.D3.API.Audio;
/**
* Creates an API Audio from an Object Audio
* @param objectAudio
* @constructor
*/
GameLib.D3.API.Audio.FromObject = function(objectAudio) {
var apiCamera = null;
if (objectAudio.camera) {
if (objectAudio.camera instanceof Object) {
apiCamera = GameLib.D3.API.Camera.FromObject(objectAudio.camera);
} else {
apiCamera = objectAudio.camera;
}
}
return new GameLib.D3.API.Audio(
objectAudio.id,
objectAudio.name,
objectAudio.path,
objectAudio.loop,
objectAudio.volume,
apiCamera,
objectAudio.overplay,
objectAudio.paused,
objectAudio.parentEntity
);
};
/**
* BoneWeight object - associates a vertex to a bone with some weight
* @param boneIndex int
* @param weight float
* @constructor
*/
GameLib.D3.API.BoneWeight = function (
boneIndex,
weight
) {
this.boneIndex = boneIndex;
this.weight = weight;
};
/**
* Object to GameLib.D3.API.BoneWeight
* @param objectBoneWeight
* @returns {GameLib.D3.API.BoneWeight}
* @constructor
*/
GameLib.D3.API.BoneWeight.FromObject = function(objectBoneWeight) {
return new GameLib.D3.API.BoneWeight(
objectBoneWeight.boneIndex,
objectBoneWeight.weight
)
};
/**
* Bone Superset
* @param id
* @param name string
* @param childBoneIds
* @param parentBoneIds
* @param quaternion GameLib.API.Quaternion
* @param position GameLib.API.Vector3
* @param scale GameLib.API.Vector3
* @param up GameLib.API.Vector3
* @constructor
*/
GameLib.D3.API.Bone = function (
id,
name,
childBoneIds,
parentBoneIds,
position,
quaternion,
scale,
up
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Bone (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(childBoneIds)) {
childBoneIds = [];
}
this.childBoneIds = childBoneIds;
if (GameLib.Utils.UndefinedOrNull(parentBoneIds)) {
parentBoneIds = [];
}
this.parentBoneIds = parentBoneIds;
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3();
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(quaternion)) {
quaternion = new GameLib.API.Quaternion();
}
this.quaternion = quaternion;
if (GameLib.Utils.UndefinedOrNull(scale)) {
scale = new GameLib.API.Vector3(1,1,1);
}
this.scale = scale;
if (GameLib.Utils.UndefinedOrNull(up)) {
up = new GameLib.API.Vector3(0,1,0);
}
this.up = up;
};
/**
* Returns an API bone from an Object bone
* @param objectBone
* @constructor
*/
GameLib.D3.API.Bone.FromObject = function(objectBone) {
return new GameLib.D3.API.Bone(
objectBone.id,
objectBone.name,
objectBone.childBoneIds,
objectBone.parentBoneIds,
GameLib.API.Vector3.FromObject(objectBone.position),
GameLib.API.Quaternion.FromObject(objectBone.quaternion),
GameLib.API.Vector3.FromObject(objectBone.scale),
GameLib.API.Vector3.FromObject(objectBone.up)
);
};
/**
* Raw Broadphase API object - should always correspond with the Broadphase Schema
* @param id
* @param name
* @param broadphaseType
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Broadphase = function(
id,
name,
broadphaseType,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Broadphase (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(broadphaseType)) {
broadphaseType = GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE;
}
this.broadphaseType = broadphaseType;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Broadphase.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Broadphase.prototype.constructor = GameLib.D3.API.Broadphase;
/**
* Creates an API Broadphase from an Object Broadphase
* @param objectBroadphase
* @constructor
*/
GameLib.D3.API.Broadphase.FromObject = function(objectBroadphase) {
return new GameLib.D3.API.Broadphase(
objectBroadphase.id,
objectBroadphase.name,
objectBroadphase.broadphaseType,
objectBroadphase.parentEntity
);
};
/**
* Raw Camera API object - should always correspond with the Camera Schema
* @param id
* @param name
* @param cameraType GameLib.D3.Camera.CAMERA_TYPE_*
* @param fov
* @param aspect
* @param near
* @param far
* @param position GameLib.API.Vector3
* @param lookAt GameLib.API.Vector3
* @param minX
* @param maxX
* @param minY
* @param maxY
* @param minZ
* @param maxZ
* @param offsetX
* @param offsetY
* @param quaternion GameLib.Quaternion
* @param parentEntity
* @param eyeSeparation
* @param focalLength
* @constructor
*/
GameLib.D3.API.Camera = function(
id,
cameraType,
name,
fov,
aspect,
near,
far,
position,
lookAt,
minX,
maxX,
minY,
maxY,
minZ,
maxZ,
offsetX,
offsetY,
quaternion,
parentEntity,
eyeSeparation,
focalLength
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(cameraType)) {
cameraType = GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE;
}
this.cameraType = cameraType;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Camera (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(fov)) {
fov = 75;
}
this.fov = fov;
if (GameLib.Utils.UndefinedOrNull(aspect)) {
aspect = window.innerWidth / window.innerHeight;
}
this.aspect = aspect;
if (GameLib.Utils.UndefinedOrNull(near)) {
near = 0.01;
}
this.near = near;
if (GameLib.Utils.UndefinedOrNull(far)) {
far = 1000;
}
this.far = far;
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3(
15,
15,
15
);
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(quaternion)) {
quaternion = new GameLib.API.Quaternion();
}
this.quaternion = quaternion;
if (GameLib.Utils.UndefinedOrNull(lookAt)) {
lookAt = new GameLib.API.Vector3(
0,
0,
0
);
}
this.lookAt = lookAt;
if (GameLib.Utils.UndefinedOrNull(minX)) {
minX = -100;
}
this.minX = minX;
if (GameLib.Utils.UndefinedOrNull(maxX)) {
maxX = 100;
}
this.maxX = maxX;
if (GameLib.Utils.UndefinedOrNull(minY)) {
minY = -100;
}
this.minY = minY;
if (GameLib.Utils.UndefinedOrNull(maxY)) {
maxY = 100;
}
this.maxY = maxY;
if (GameLib.Utils.UndefinedOrNull(minZ)) {
minZ = -100;
}
this.minZ = minZ;
if (GameLib.Utils.UndefinedOrNull(maxZ)) {
maxZ = 100;
}
this.maxZ = maxZ;
if (GameLib.Utils.UndefinedOrNull(offsetX)) {
offsetX = 0;
}
this.offsetX = offsetX;
if (GameLib.Utils.UndefinedOrNull(offsetY)) {
offsetY = 0;
}
this.offsetY = offsetY;
if (GameLib.Utils.UndefinedOrNull(eyeSeparation)) {
eyeSeparation = 30;
}
this.eyeSeparation = eyeSeparation;
if (GameLib.Utils.UndefinedOrNull(focalLength)) {
focalLength = 150;
}
this.focalLength = focalLength;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Camera.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Camera.prototype.constructor = GameLib.D3.API.Camera;
/**
* Creates an API camera from an Object camera
* @param objectCamera
* @constructor
*/
GameLib.D3.API.Camera.FromObject = function(objectCamera) {
return new GameLib.D3.API.Camera(
objectCamera.id,
objectCamera.cameraType,
objectCamera.name,
objectCamera.fov,
objectCamera.aspect,
objectCamera.near,
objectCamera.far,
GameLib.API.Vector3.FromObject(objectCamera.position),
GameLib.API.Vector3.FromObject(objectCamera.lookAt),
objectCamera.minX,
objectCamera.maxX,
objectCamera.minY,
objectCamera.maxY,
objectCamera.minZ,
objectCamera.maxZ,
objectCamera.offsetX,
objectCamera.offsetY,
GameLib.API.Quaternion.FromObject(objectCamera.quaternion),
objectCamera.parentEntity,
objectCamera.eyeSeparation,
objectCamera.focalLength
);
};
/**
* 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
);
};
/**
* This component renders a scene
* @param id String
* @param name String
* @param renderer GameLib.D3.Renderer
* @param renderTarget GameLib.D3.API.RenderTarget
* @param passes GameLib.D3.API.Pass[]
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Composer = function (
id,
name,
renderer,
renderTarget,
passes,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Composer (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(renderer)) {
renderer = null;
}
this.renderer = renderer;
if (GameLib.Utils.UndefinedOrNull(renderTarget)) {
renderTarget = null;
}
this.renderTarget = renderTarget;
if (GameLib.Utils.UndefinedOrNull(passes)) {
passes = [];
}
this.passes = passes;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Composer.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Composer.prototype.constructor = GameLib.D3.API.Composer;
/**
* Object to GameLib.D3.API.Composer
* @param objectComponent
* @constructor
*/
GameLib.D3.API.Composer.FromObject = function(objectComponent) {
return new GameLib.D3.API.Composer(
objectComponent.id,
objectComponent.name,
objectComponent.renderer,
objectComponent.renderTarget,
objectComponent.passes,
objectComponent.parentEntity
);
};
/**
* Raw Controls API object
* @param id
* @param controlsType
* @param name
* @param domElement
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Controls = function(
id,
controlsType,
name,
domElement,
// fullscreen,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(controlsType)) {
if (this instanceof GameLib.D3.Controls.Editor) {
controlsType = GameLib.D3.Controls.CONTROLS_TYPE_EDITOR;
}
if (this instanceof GameLib.D3.Controls.Touch) {
controlsType = GameLib.D3.Controls.CONTROLS_TYPE_TOUCH;
}
if (this instanceof GameLib.D3.Controls.Keyboard) {
controlsType = GameLib.D3.Controls.CONTROLS_TYPE_KEYBOARD;
}
if (this instanceof GameLib.D3.Controls.Mouse) {
controlsType = GameLib.D3.Controls.CONTROLS_TYPE_MOUSE;
}
if (GameLib.Utils.UndefinedOrNull(controlsType)) {
throw new Error('Could not determine controls type from this');
}
}
this.controlsType = controlsType;
if (GameLib.Utils.UndefinedOrNull(name)) {
if (controlsType === GameLib.D3.Controls.CONTROLS_TYPE_EDITOR) {
name = 'Editing Controls';
}
if (controlsType === GameLib.D3.Controls.CONTROLS_TYPE_TOUCH) {
name = 'Touch Controls';
}
if (controlsType === GameLib.D3.Controls.CONTROLS_TYPE_KEYBOARD) {
name = 'Keyboard Controls';
}
if (controlsType === GameLib.D3.Controls.CONTROLS_TYPE_MOUSE) {
name = 'Mouse Controls';
}
name += ' (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(domElement)) {
domElement = null;
}
this.domElement = domElement;
// if (GameLib.Utils.UndefinedOrNull(fullscreen)) {
// fullscreen = false;
// }
// this.fullscreen = fullscreen;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Controls.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Controls.prototype.constructor = GameLib.D3.API.Controls;
/**
* Returns an API Controls from an Object
* @param objectControls
* @constructor
*/
GameLib.D3.API.Controls.FromObject = function (objectControls){
return new GameLib.D3.API.Controls(
objectControls.id,
objectControls.controlsType,
objectControls.name,
objectControls.domElement,
objectControls.parentEntity
);
};
/**
* Custom Code Component
* @param id
* @param name
* @param eventId
* @param code
* @param parentEntity
* @constructor
*/
GameLib.D3.API.CustomCode = function (
id,
name,
eventId,
code,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'CustomCode (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(eventId)) {
eventId = 42;
}
this.eventId = eventId;
if (GameLib.Utils.UndefinedOrNull(code)) {
code = "return null;\n//@ sourceURL=" + this.name + ".js";
}
this.code = code;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.CustomCode.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.CustomCode.prototype.constructor = GameLib.D3.API.CustomCode;
/**
* Object to GameLib.D3.API.CustomCode
* @param objectComponent
* @returns {GameLib.D3.API.CustomCode}
* @constructor
*/
GameLib.D3.API.CustomCode.FromObject = function(objectComponent) {
return new GameLib.D3.API.CustomCode(
objectComponent.id,
objectComponent.name,
objectComponent.eventId,
objectComponent.code,
objectComponent.parentEntity
);
};
/**
* Face
* @param id
* @param name
* @param v0index
* @param v1index
* @param v2index
* @param materialIndex
* @param uvs [[v0uv (GameLib.Vector2), v1uv(GameLib.Vector2), v2uv(GameLib.Vector2)]]
* @param color
* @param vertexColors
* @param vertexNormals
* @param normal
* @constructor
*/
GameLib.D3.API.Face = function(
id,
name,
v0index,
v1index,
v2index,
materialIndex,
uvs,
color,
vertexColors,
vertexNormals,
normal
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Face ' + id;
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(v0index)) {
v0index = -1;
}
this.v0index = v0index;
if (GameLib.Utils.UndefinedOrNull(v1index)) {
v1index = -1;
}
this.v1index = v1index;
if (GameLib.Utils.UndefinedOrNull(v2index)) {
v2index = -1;
}
this.v2index = v2index;
if (GameLib.Utils.UndefinedOrNull(materialIndex)) {
materialIndex = -1;
}
this.materialIndex = materialIndex;
if (GameLib.Utils.UndefinedOrNull(uvs)) {
uvs = [[]];
}
this.uvs = uvs;
if (GameLib.Utils.UndefinedOrNull(color)) {
color = null;
}
this.color = color;
if (GameLib.Utils.UndefinedOrNull(vertexColors)) {
vertexColors = [];
}
this.vertexColors = vertexColors;
if (GameLib.Utils.UndefinedOrNull(vertexNormals)) {
vertexNormals = [];
}
this.vertexNormals = vertexNormals;
if (GameLib.Utils.UndefinedOrNull(normal)) {
normal = null;
}
this.normal = normal;
};
/**
* We don't inherit from component - it makes the entitymanager too heavy - all faces end up in the register etc..
*/
// GameLib.D3.API.Face.prototype = Object.create(GameLib.Component.prototype);
// GameLib.D3.API.Face.prototype.constructor = GameLib.D3.API.Face;
/**
* Returns an API Face from a data object
* @constructor
* @param objectFace
*/
GameLib.D3.API.Face.FromObject = function(objectFace) {
var apiUvs = objectFace.uvs.reduce(
function(result, uvArray, index) {
result[index] = uvArray.reduce(
function(uvResult, uv) {
uvResult.push(GameLib.API.Vector2.FromObject(uv));
return uvResult;
},
[]
);
return result;
},
[]
);
var apiVertexColors = objectFace.vertexColors.map(
function(vertexColor) {
return GameLib.API.Color.FromObject(vertexColor);
}
);
var apiColor = null;
if (objectFace.color) {
apiColor = GameLib.API.Color.FromObject(objectFace.color);
}
var apiVertexNormals = objectFace.vertexNormals.map(
function(vertexNormal) {
return GameLib.API.Vector3.FromObject(vertexNormal);
}
);
var apiNormal = null;
if (objectFace.normal) {
apiNormal = GameLib.API.Vector3.FromObject(objectFace.normal);
}
return new GameLib.D3.API.Face(
objectFace.id,
objectFace.name,
objectFace.v0index,
objectFace.v1index,
objectFace.v2index,
objectFace.materialIndex,
apiUvs,
apiColor,
apiVertexColors,
apiVertexNormals,
apiNormal
);
};
/**
* Clone a Face
* @returns {GameLib.D3.API.Face}
*/
GameLib.D3.API.Face.prototype.clone = function(){
return new GameLib.D3.API.Face(
this.id,
this.name,
this.v0index,
this.v1index,
this.v2index,
this.materialIndex,
this.uvs,
this.color,
this.vertexColors,
this.vertexNormals,
this.normal
);
};
/**
* Returns true if two triangles are equal (their vertex indices match in some order)
* @param triangle
* @returns {boolean}
*/
GameLib.D3.API.Face.prototype.equals = function(triangle) {
return (
(
(this.v0index === triangle.v0index) &&
(this.v1index === triangle.v1index) &&
(this.v2index === triangle.v2index)
)
||
(
(this.v0index === triangle.v0index) &&
(this.v1index === triangle.v2index) &&
(this.v2index === triangle.v1index)
)
||
(
(this.v0index === triangle.v1index) &&
(this.v1index === triangle.v0index) &&
(this.v2index === triangle.v2index)
)
||
(
(this.v0index === triangle.v1index) &&
(this.v1index === triangle.v2index) &&
(this.v2index === triangle.v0index)
)
||
(
(this.v0index === triangle.v2index) &&
(this.v1index === triangle.v0index) &&
(this.v2index === triangle.v1index)
)
||
(
(this.v0index === triangle.v2index) &&
(this.v1index === triangle.v1index) &&
(this.v2index === triangle.v0index)
)
);
};
/**
* Raw Fog API object - should always correspond with the Fog Schema
* @param id String
* @param name String
* @param exponential
* @param color
* @param near
* @param far
* @param density
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Fog = function(
id,
name,
exponential,
color,
near,
far,
density,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Fog (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(exponential)) {
exponential = false;
}
this.exponential = exponential;
if (GameLib.Utils.UndefinedOrNull(color)) {
color = new GameLib.API.Color(1, 1, 1, 1)
}
this.color = color;
if (GameLib.Utils.UndefinedOrNull(near)) {
near = 1;
}
this.near = near;
if (GameLib.Utils.UndefinedOrNull(far)) {
far = 1000;
}
this.far = far;
if (GameLib.Utils.UndefinedOrNull(density)) {
density = 0.00025;
}
this.density = density;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Fog.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Fog.prototype.constructor = GameLib.D3.API.Fog;
/**
* Returns an API scene from an Object scene
* @param objectFog
* @constructor
*/
GameLib.D3.API.Fog.FromObject = function(objectFog) {
return new GameLib.D3.API.Fog(
objectFog.id,
objectFog.name,
objectFog.exponential,
objectFog.color,
objectFog.near,
objectFog.far,
objectFog.density,
objectFog.parentEntity
);
};
/**
* Raw Font API object - should always correspond with the Font Schema
* @param id
* @param name
* @param url
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Font = function(
id,
name,
url,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Font (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(url)) {
url = '/apiRelative/path/to/font';
}
this.url = url;
if (GameLib.Utils.UndefinedOrNull(parentEntity)){
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Font.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Font.prototype.constructor = GameLib.D3.API.Font;
/**
* Returns an API light from an Object light
* @param objectFont
* @constructor
*/
GameLib.D3.API.Font.FromObject = function(objectFont) {
return new GameLib.D3.API.Font(
objectFont.id,
objectFont.name,
objectFont.url,
objectFont.parentEntity
);
};
/**
* Raw FrictionContactMaterial API object - should always correspond with the FrictionContactMaterial Schema
* @param id
* @param name
* @param material1
* @param material2
* @param friction
* @param restitution
* @param contactEquationStiffness
* @param contactEquationRelaxation
* @param frictionEquationStiffness
* @param frictionEquationRelaxation
* @param parentEntity
* @constructor
*/
GameLib.D3.API.FrictionContactMaterial = function(
id,
name,
materials,
friction,
restitution,
contactEquationStiffness,
contactEquationRelaxation,
frictionEquationStiffness,
frictionEquationRelaxation,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Friction Material (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(materials)) {
materials = [];
}
this.materials = materials;
if (GameLib.Utils.UndefinedOrNull(friction)) {
friction = 0.3;
}
this.friction = friction;
if (GameLib.Utils.UndefinedOrNull(restitution)) {
restitution = 0.3;
}
this.restitution = restitution;
if (GameLib.Utils.UndefinedOrNull(contactEquationStiffness)) {
contactEquationStiffness = 1e7;
}
this.contactEquationStiffness = contactEquationStiffness;
if (GameLib.Utils.UndefinedOrNull(contactEquationRelaxation)) {
contactEquationRelaxation = 3;
}
this.contactEquationRelaxation = contactEquationRelaxation;
if (GameLib.Utils.UndefinedOrNull(frictionEquationStiffness)) {
frictionEquationStiffness = 1e7;
}
this.frictionEquationStiffness = frictionEquationStiffness;
if (GameLib.Utils.UndefinedOrNull(frictionEquationRelaxation)) {
frictionEquationRelaxation = 3;
}
this.frictionEquationRelaxation = frictionEquationRelaxation;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.FrictionContactMaterial.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.FrictionContactMaterial.prototype.constructor = GameLib.D3.API.FrictionContactMaterial;
/**
* Creates an API FrictionContactMaterial from an Object FrictionContactMaterial
* @param objectFrictionContactMaterial
* @constructor
*/
GameLib.D3.API.FrictionContactMaterial.FromObject = function(objectFrictionContactMaterial) {
return new GameLib.D3.API.FrictionContactMaterial(
objectFrictionContactMaterial.id,
objectFrictionContactMaterial.name,
objectFrictionContactMaterial.materials,
objectFrictionContactMaterial.friction,
objectFrictionContactMaterial.restitution,
objectFrictionContactMaterial.contactEquationStiffness,
objectFrictionContactMaterial.contactEquationRelaxation,
objectFrictionContactMaterial.frictionEquationStiffness,
objectFrictionContactMaterial.frictionEquationRelaxation,
objectFrictionContactMaterial.parentEntity
);
};
/**
* Raw FrictionMaterial API object - should always correspond with the FrictionMaterial Schema
* @param id
* @param name
* @param friction
* @param restitution
* @param parentEntity
* @constructor
*/
GameLib.D3.API.FrictionMaterial = function(
id,
name,
friction,
restitution,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Friction Material (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(friction)) {
friction = -1;
}
this.friction = friction;
if (GameLib.Utils.UndefinedOrNull(restitution)) {
restitution = -1;
}
this.restitution = restitution;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.FrictionMaterial.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.FrictionMaterial.prototype.constructor = GameLib.D3.API.FrictionMaterial;
/**
* Creates an API FrictionMaterial from an Object FrictionMaterial
* @param objectFrictionMaterial
* @constructor
*/
GameLib.D3.API.FrictionMaterial.FromObject = function(objectFrictionMaterial) {
return new GameLib.D3.API.FrictionMaterial(
objectFrictionMaterial.id,
objectFrictionMaterial.name,
objectFrictionMaterial.friction,
objectFrictionMaterial.restitution,
objectFrictionMaterial.parentEntity
);
};
/**
* Raw ImageFactory API object - should always correspond with the ImageFactory Schema
* @param id
* @param name
* @param baseUrl String
* @param parentEntity
* @constructor
*/
GameLib.D3.API.ImageFactory = function(
id,
name,
baseUrl,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'ImageFactory (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(baseUrl)) {
baseUrl = '';
console.warn('No baseURL defined for image factory');
}
this.baseUrl = baseUrl;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.ImageFactory.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.ImageFactory.prototype.constructor = GameLib.D3.API.ImageFactory;
/**
* Returns an API ImageFactory from an Object ImageFactory
* @param objectImageFactory
* @constructor
*/
GameLib.D3.API.ImageFactory.FromObject = function(objectImageFactory) {
return new GameLib.D3.API.ImageFactory(
objectImageFactory.id,
objectImageFactory.name,
objectImageFactory.baseUrl,
objectImageFactory.parentEntity
);
};
/**
* Image
* @param id
* @param name
* @param fileName
* @param extension
* @param path
* @param contentType
* @param size
* @param parentEntity GameLib.Entity
* @constructor
*/
GameLib.D3.API.Image = function(
id,
name,
fileName,
extension,
path,
contentType,
size,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Image ' + id;
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(fileName)) {
fileName = GameLib.Utils.LowerUnderscore(name);
}
this.fileName = fileName;
if (GameLib.Utils.UndefinedOrNull(extension)) {
extension = '.unknown';
}
this.extension = extension;
if (GameLib.Utils.UndefinedOrNull(path)) {
path = '/';
}
this.path = path;
if (GameLib.Utils.UndefinedOrNull(contentType)) {
contentType = 'application/octet-stream';
if (this.extension.match(/(png)$/i)) {
contentType = 'image/png';
}
if (this.extension.match(/(jpg|jpeg)$/i)) {
contentType = 'image/jpeg';
}
if (this.extension.match(/(gif)$/i)) {
contentType = 'image/gif';
}
}
this.contentType = contentType;
if (GameLib.Utils.UndefinedOrNull(size)) {
size = 0;
}
this.size = size;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Image.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Image.prototype.constructor = GameLib.D3.API.Image;
/**
* Returns an API light from an Object light
* @constructor
* @param objectImage
*/
GameLib.D3.API.Image.FromObject = function(objectImage) {
return new GameLib.D3.API.Image(
objectImage.id,
objectImage.name,
objectImage.fileName,
objectImage.extension,
objectImage.path,
objectImage.contentType,
objectImage.size,
objectImage.parentEntity
);
};
/**
* Raw Light API object - should always correspond with the Light Schema
* @param id
* @param lightType
* @param name
* @param color
* @param intensity
* @param position
* @param targetPosition
* @param quaternion
* @param rotation
* @param scale
* @param distance
* @param decay
* @param power
* @param angle
* @param penumbra
* @param parentScene
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Light = function(
id,
lightType,
name,
color,
intensity,
position,
targetPosition,
quaternion,
rotation,
scale,
distance,
decay,
power,
angle,
penumbra,
parentScene,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(lightType)) {
lightType = GameLib.D3.Light.LIGHT_TYPE_AMBIENT;
}
this.lightType = lightType;
if (GameLib.Utils.UndefinedOrNull(name)) {
if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_AMBIENT) {
name = 'Ambient ';
}
if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL) {
name = 'Directional ';
}
if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_POINT) {
name = 'Point ';
}
if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_SPOT) {
name = 'Spot ';
}
name += 'Light (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(color)) {
color = new GameLib.API.Color(1,1,1,1);
}
this.color = color;
if (GameLib.Utils.UndefinedOrNull(intensity)) {
intensity = 1;
}
this.intensity = intensity;
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3(10,10,10);
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(targetPosition)) {
targetPosition = new GameLib.API.Vector3(0,0,0);
}
this.targetPosition = targetPosition;
if (GameLib.Utils.UndefinedOrNull(quaternion)){
quaternion = new GameLib.API.Quaternion();
}
this.quaternion = quaternion;
if (GameLib.Utils.UndefinedOrNull(rotation)){
rotation = new GameLib.API.Vector3(0,0,0);
}
this.rotation = rotation;
if (GameLib.Utils.UndefinedOrNull(scale)){
scale = new GameLib.API.Vector3(1,1,1);
}
this.scale = scale;
if (GameLib.Utils.UndefinedOrNull(distance)){
distance = 0;
}
this.distance = distance;
if (GameLib.Utils.UndefinedOrNull(decay)){
decay = 1;
}
this.decay = decay;
if (GameLib.Utils.UndefinedOrNull(power)){
power = 4 * Math.PI;
}
this.power = power;
if (GameLib.Utils.UndefinedOrNull(angle)){
angle = Math.PI / 3;
}
this.angle = angle;
if (GameLib.Utils.UndefinedOrNull(penumbra)){
penumbra = 0;
}
this.penumbra = penumbra;
if (GameLib.Utils.UndefinedOrNull(parentScene)){
parentScene = null;
}
this.parentScene = parentScene;
if (GameLib.Utils.UndefinedOrNull(parentEntity)){
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Light.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Light.prototype.constructor = GameLib.D3.API.Light;
/**
* Returns an API light from an Object light
* @param objectLight
* @constructor
*/
GameLib.D3.API.Light.FromObject = function(objectLight) {
return new GameLib.D3.API.Light(
objectLight.id,
objectLight.lightType,
objectLight.name,
GameLib.API.Color.FromObject(objectLight.color),
objectLight.intensity,
GameLib.API.Vector3.FromObject(objectLight.position),
GameLib.API.Vector3.FromObject(objectLight.targetPosition),
GameLib.API.Quaternion.FromObject(objectLight.quaternion),
GameLib.API.Vector3.FromObject(objectLight.rotation),
GameLib.API.Vector3.FromObject(objectLight.scale),
objectLight.distance,
objectLight.decay,
objectLight.power,
objectLight.angle,
objectLight.penumbra,
objectLight.parentScene,
objectLight.parentEntity
);
};
/**
* Looks from currentPosition to targetPosition (default up is 0,1,0)
* @param id
* @param name
* @param currentComponent GameLib.Component
* @param targetComponent GameLib.Component
* @param targetPositionOffset GameLib.API.Vector3
* @param rotationSpeed Number
* @param parentEntity
* @constructor
*/
GameLib.D3.API.LookAt = function (
id,
name,
currentComponent,
targetComponent,
targetPositionOffset,
rotationSpeed,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = this.constructor.name;
}
this.name = name;
if(GameLib.Utils.UndefinedOrNull(currentComponent)) {
currentComponent = null;
}
this.currentComponent = currentComponent;
if(GameLib.Utils.UndefinedOrNull(targetComponent)) {
targetComponent = null;
}
this.targetComponent = targetComponent;
if(GameLib.Utils.UndefinedOrNull(targetPositionOffset)) {
targetPositionOffset = new GameLib.API.Vector3(0, 0, 0);
}
this.targetPositionOffset = targetPositionOffset;
if (GameLib.Utils.UndefinedOrNull(rotationSpeed)) {
rotationSpeed = 22.0;
}
this.rotationSpeed = rotationSpeed;
this.lookAtMatrix = new GameLib.API.Matrix4();
this.up = new GameLib.API.Vector3(0, 1, 0);
this.currentRotation = new GameLib.API.Quaternion();
this.targetPosition = new GameLib.API.Vector3();
if(GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.LookAt.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.LookAt.prototype.constructor = GameLib.D3.API.LookAt;
/**
* Object to GameLib.D3.API.LookAt
* @param objectComponent
* @returns {GameLib.D3.API.LookAt}
* @constructor
*/
GameLib.D3.API.LookAt.FromObject = function(objectComponent) {
return new GameLib.D3.API.LookAt(
objectComponent.id,
objectComponent.name,
objectComponent.currentComponent,
objectComponent.targetComponent,
GameLib.API.Vector3.FromObject(objectComponent.targetPositionOffset),
objectComponent.rotationSpeed,
objectComponent.parentEntity
);
};
/**
* Raw material API object - should always correspond with the Material Schema
* @param id
* @param materialType
* @param name
* @param opacity
* @param side
* @param transparent
* @param specular
* @param lightMapIntensity
* @param aoMapIntensity
* @param color
* @param emissive
* @param emissiveIntensity
* @param combine
* @param shininess
* @param reflectivity
* @param refractionRatio
* @param fog
* @param wireframe
* @param wireframeLineWidth
* @param wireframeLineCap
* @param wireframeLineJoin
* @param vertexColors
* @param skinning
* @param morphTargets
* @param morphNormals
* @param lineWidth
* @param lineCap
* @param lineJoin
* @param dashSize
* @param gapWidth
* @param blending
* @param blendSrc
* @param blendDst
* @param blendEquation
* @param depthTest
* @param depthFunc
* @param depthWrite
* @param polygonOffset
* @param polygonOffsetFactor
* @param polygonOffsetUnits
* @param alphaTest
* @param clippingPlanes
* @param clipShadows
* @param visible
* @param overdraw
* @param flatShading
* @param bumpScale
* @param normalScale
* @param displacementScale
* @param displacementBias
* @param roughness
* @param metalness
* @param pointSize
* @param pointSizeAttenuation
* @param spriteRotation
* @param envMapIntensity
* @param alphaMap
* @param aoMap
* @param bumpMap
* @param diffuseMap
* @param displacementMap
* @param emissiveMap
* @param environmentMap
* @param lightMap
* @param metalnessMap
* @param normalMap
* @param roughnessMap
* @param specularMap
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Material = function(
id,
materialType,
name,
opacity,
side,
transparent,
specular,
lightMapIntensity,
aoMapIntensity,
color,
emissive,
emissiveIntensity,
combine,
shininess,
reflectivity,
refractionRatio,
fog,
wireframe,
wireframeLineWidth,
wireframeLineCap,
wireframeLineJoin,
vertexColors,
skinning,
morphTargets,
morphNormals,
lineWidth,
lineCap,
lineJoin,
dashSize,
gapWidth,
blending,
blendSrc,
blendDst,
blendEquation,
depthTest,
depthFunc,
depthWrite,
polygonOffset,
polygonOffsetFactor,
polygonOffsetUnits,
alphaTest,
clippingPlanes,
clipShadows,
visible,
overdraw,
flatShading,
bumpScale,
normalScale,
displacementScale,
displacementBias,
roughness,
metalness,
pointSize,
pointSizeAttenuation,
spriteRotation,
envMapIntensity,
alphaMap,
aoMap,
bumpMap,
diffuseMap,
displacementMap,
emissiveMap,
environmentMap,
lightMap,
metalnessMap,
normalMap,
roughnessMap,
specularMap,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(materialType)) {
materialType = GameLib.D3.Material.MATERIAL_TYPE_STANDARD;
}
this.materialType = materialType;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Material (' + materialType + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(opacity)) {
opacity = 1.0;
}
this.opacity = opacity;
if (GameLib.Utils.UndefinedOrNull(side)) {
side = GameLib.D3.Material.TYPE_FRONT_SIDE;
}
this.side = side;
if (GameLib.Utils.UndefinedOrNull(transparent)) {
transparent = false;
}
this.transparent = transparent;
if (GameLib.Utils.UndefinedOrNull(specular)) {
specular = new GameLib.API.Color(0.06, 0.06, 0.06, 0.06);
}
this.specular = specular;
if (GameLib.Utils.UndefinedOrNull(lightMapIntensity)) {
lightMapIntensity = 1;
}
this.lightMapIntensity = lightMapIntensity;
if (GameLib.Utils.UndefinedOrNull(aoMapIntensity)) {
aoMapIntensity = 1;
}
this.aoMapIntensity = aoMapIntensity;
if (GameLib.Utils.UndefinedOrNull(color)) {
color = new GameLib.API.Color(1, 1, 1, 1)
}
this.color = color;
if (GameLib.Utils.UndefinedOrNull(emissive)) {
emissive = new GameLib.API.Color(0, 0, 0, 0);
}
this.emissive = emissive;
if (GameLib.Utils.UndefinedOrNull(emissiveIntensity)) {
emissiveIntensity = 1;
}
this.emissiveIntensity = emissiveIntensity;
if (GameLib.Utils.UndefinedOrNull(combine)) {
combine = GameLib.D3.Material.TYPE_MULTIPLY_OPERATION;
}
this.combine = combine;
if (GameLib.Utils.UndefinedOrNull(shininess)) {
shininess = 30;
}
this.shininess = shininess;
if (GameLib.Utils.UndefinedOrNull(reflectivity)) {
reflectivity = 1;
}
this.reflectivity = reflectivity;
if (GameLib.Utils.UndefinedOrNull(refractionRatio)) {
refractionRatio = 0.98;
}
this.refractionRatio = refractionRatio;
if (GameLib.Utils.UndefinedOrNull(fog)) {
fog = true;
}
this.fog = fog;
if (GameLib.Utils.UndefinedOrNull(wireframe)) {
wireframe = false;
}
this.wireframe = wireframe;
if (GameLib.Utils.UndefinedOrNull(wireframeLineWidth)) {
wireframeLineWidth = 1;
}
this.wireframeLineWidth = wireframeLineWidth;
if (GameLib.Utils.UndefinedOrNull(wireframeLineCap)) {
wireframeLineCap = 'round';
}
this.wireframeLineCap = wireframeLineCap;
if (GameLib.Utils.UndefinedOrNull(wireframeLineJoin)) {
wireframeLineJoin = 'round';
}
this.wireframeLineJoin = wireframeLineJoin;
if (GameLib.Utils.UndefinedOrNull(vertexColors)) {
vertexColors = GameLib.D3.Material.TYPE_NO_COLORS;
}
this.vertexColors = vertexColors;
if (GameLib.Utils.UndefinedOrNull(skinning)) {
skinning = false;
}
this.skinning = skinning;
if (GameLib.Utils.UndefinedOrNull(morphTargets)) {
morphTargets = false;
}
this.morphTargets = morphTargets;
if (GameLib.Utils.UndefinedOrNull(morphNormals)) {
morphNormals = false;
}
this.morphNormals = morphNormals;
if (GameLib.Utils.UndefinedOrNull(overdraw)) {
overdraw = 0;
}
this.overdraw = overdraw;
if (GameLib.Utils.UndefinedOrNull(lineWidth)) {
lineWidth = 1;
}
this.lineWidth = lineWidth;
if (GameLib.Utils.UndefinedOrNull(lineCap)) {
lineCap = 'round';
}
this.lineCap = lineCap;
if (GameLib.Utils.UndefinedOrNull(lineJoin)) {
lineJoin = 'round';
}
this.lineJoin = lineJoin;
if (GameLib.Utils.UndefinedOrNull(dashSize)) {
dashSize = 3;
}
this.dashSize = dashSize;
if (GameLib.Utils.UndefinedOrNull(gapWidth)) {
gapWidth = 1;
}
this.gapWidth = gapWidth;
if (GameLib.Utils.UndefinedOrNull(blending)) {
blending = GameLib.D3.Material.TYPE_NORMAL_BLENDING;
}
this.blending = blending;
if (GameLib.Utils.UndefinedOrNull(blendSrc)) {
blendSrc = GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR;
}
this.blendSrc = blendSrc;
if (GameLib.Utils.UndefinedOrNull(blendDst)) {
blendDst = GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR;
}
this.blendDst = blendDst;
if (GameLib.Utils.UndefinedOrNull(blendEquation)) {
blendEquation = GameLib.D3.Material.TYPE_ADD_EQUATION;
}
this.blendEquation = blendEquation;
if (GameLib.Utils.UndefinedOrNull(depthTest)) {
depthTest = true;
}
this.depthTest = depthTest;
if (GameLib.Utils.UndefinedOrNull(depthFunc)) {
depthFunc = GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH;
}
this.depthFunc = depthFunc;
if (GameLib.Utils.UndefinedOrNull(depthWrite)) {
depthWrite = true;
}
this.depthWrite = depthWrite;
if (GameLib.Utils.UndefinedOrNull(polygonOffset)) {
polygonOffset = false;
}
this.polygonOffset = polygonOffset;
if (GameLib.Utils.UndefinedOrNull(polygonOffsetFactor)) {
polygonOffsetFactor = 1;
}
this.polygonOffsetFactor = polygonOffsetFactor;
if (GameLib.Utils.UndefinedOrNull(polygonOffsetUnits)) {
polygonOffsetUnits = 1;
}
this.polygonOffsetUnits = polygonOffsetUnits;
if (GameLib.Utils.UndefinedOrNull(alphaTest)) {
alphaTest = 0;
}
this.alphaTest = alphaTest;
if (GameLib.Utils.UndefinedOrNull(clippingPlanes)) {
clippingPlanes = [];
}
this.clippingPlanes = clippingPlanes;
if (GameLib.Utils.UndefinedOrNull(clipShadows)) {
clipShadows = false;
}
this.clipShadows = clipShadows;
if (GameLib.Utils.UndefinedOrNull(visible)) {
visible = true;
}
this.visible = visible;
if (GameLib.Utils.UndefinedOrNull(flatShading)) {
flatShading = false;
}
this.flatShading = flatShading;
if (GameLib.Utils.UndefinedOrNull(bumpScale)) {
bumpScale = 1;
}
this.bumpScale = bumpScale;
if (GameLib.Utils.UndefinedOrNull(normalScale)) {
normalScale = 1;
}
this.normalScale = normalScale;
if (GameLib.Utils.UndefinedOrNull(displacementScale)) {
displacementScale = 1;
}
this.displacementScale = displacementScale;
if (GameLib.Utils.UndefinedOrNull(displacementBias)) {
displacementBias = 0;
}
this.displacementBias = displacementBias;
if (GameLib.Utils.UndefinedOrNull(roughness)) {
roughness = 0.5;
}
this.roughness = roughness;
if (GameLib.Utils.UndefinedOrNull(metalness)) {
metalness = 0.5;
}
this.metalness = metalness;
if (GameLib.Utils.UndefinedOrNull(pointSize)) {
pointSize = 1;
}
this.pointSize = pointSize;
if (GameLib.Utils.UndefinedOrNull(pointSizeAttenuation)) {
pointSizeAttenuation = true;
}
this.pointSizeAttenuation = pointSizeAttenuation;
if (GameLib.Utils.UndefinedOrNull(spriteRotation)) {
spriteRotation = 0;
}
this.spriteRotation = spriteRotation;
if (GameLib.Utils.UndefinedOrNull(envMapIntensity)) {
envMapIntensity = 1.0;
}
this.envMapIntensity = envMapIntensity;
if (GameLib.Utils.UndefinedOrNull(alphaMap)) {
alphaMap = null;
}
this.alphaMap = alphaMap;
if (GameLib.Utils.UndefinedOrNull(aoMap)) {
aoMap = null;
}
this.aoMap = aoMap;
if (GameLib.Utils.UndefinedOrNull(bumpMap)) {
bumpMap = null;
}
this.bumpMap = bumpMap;
if (GameLib.Utils.UndefinedOrNull(diffuseMap)) {
diffuseMap = null;
}
this.diffuseMap = diffuseMap;
if (GameLib.Utils.UndefinedOrNull(displacementMap)) {
displacementMap = null;
}
this.displacementMap = displacementMap;
if (GameLib.Utils.UndefinedOrNull(emissiveMap)) {
emissiveMap = null;
}
this.emissiveMap = emissiveMap;
if (GameLib.Utils.UndefinedOrNull(environmentMap)) {
environmentMap = null;
}
this.environmentMap = environmentMap;
if (GameLib.Utils.UndefinedOrNull(lightMap)) {
lightMap = null;
}
this.lightMap = lightMap;
if (GameLib.Utils.UndefinedOrNull(metalnessMap)) {
metalnessMap = null;
}
this.metalnessMap = metalnessMap;
if (GameLib.Utils.UndefinedOrNull(normalMap)) {
normalMap = null;
}
this.normalMap = normalMap;
if (GameLib.Utils.UndefinedOrNull(roughnessMap)) {
roughnessMap = null;
}
this.roughnessMap = roughnessMap;
if (GameLib.Utils.UndefinedOrNull(specularMap)) {
specularMap = null;
}
this.specularMap = specularMap;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
this.needsUpdate = false;
};
GameLib.D3.API.Material.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Material.prototype.constructor = GameLib.D3.API.Material;
/**
* Returns an API Material from an Object material
* @param objectMaterial
* @constructor
*/
GameLib.D3.API.Material.FromObject = function(objectMaterial) {
var apiAlphaMap = null;
var apiAoMap = null;
var apiBumpMap = null;
var apiDiffuseMap = null;
var apiDisplacementMap = null;
var apiEmissiveMap = null;
var apiEnvironmentMap = null;
var apiLightMap = null;
var apiMetalnessMap = null;
var apiNormalMap = null;
var apiRoughnessMap = null;
var apiSpecularMap = null;
if (objectMaterial.alphaMap) {
apiAlphaMap = objectMaterial.alphaMap;
}
if (objectMaterial.aoMap) {
apiAoMap = objectMaterial.aoMap;
}
if (objectMaterial.bumpMap) {
apiBumpMap = objectMaterial.bumpMap;
}
if (objectMaterial.diffuseMap) {
apiDiffuseMap = objectMaterial.diffuseMap;
}
if (objectMaterial.displacementMap) {
apiDisplacementMap = objectMaterial.displacementMap;
}
if (objectMaterial.emissiveMap) {
apiEmissiveMap = objectMaterial.emissiveMap;
}
if (objectMaterial.environmentMap) {
apiEnvironmentMap = objectMaterial.environmentMap;
}
if (objectMaterial.lightMap) {
apiLightMap = objectMaterial.lightMap;
}
if (objectMaterial.metalnessMap) {
apiMetalnessMap = objectMaterial.metalnessMap;
}
if (objectMaterial.normalMap) {
apiNormalMap = objectMaterial.normalMap;
}
if (objectMaterial.roughnessMap) {
apiRoughnessMap = objectMaterial.roughnessMap;
}
if (objectMaterial.specularMap) {
apiSpecularMap = objectMaterial.specularMap;
}
return new GameLib.D3.API.Material(
objectMaterial.id,
objectMaterial.materialType,
objectMaterial.name,
objectMaterial.opacity,
objectMaterial.side,
objectMaterial.transparent,
GameLib.API.Color.FromObject(objectMaterial.specular),
objectMaterial.lightMapIntensity,
objectMaterial.aoMapIntensity,
GameLib.API.Color.FromObject(objectMaterial.color),
GameLib.API.Color.FromObject(objectMaterial.emissive),
objectMaterial.emissiveIntensity,
objectMaterial.combine,
objectMaterial.shininess,
objectMaterial.reflectivity,
objectMaterial.refractionRatio,
objectMaterial.fog,
objectMaterial.wireframe,
objectMaterial.wireframeLineWidth,
objectMaterial.wireframeLineCap,
objectMaterial.wireframeLineJoin,
objectMaterial.vertexColors,
objectMaterial.skinning,
objectMaterial.morphTargets,
objectMaterial.morphNormals,
objectMaterial.lineWidth,
objectMaterial.lineCap,
objectMaterial.lineJoin,
objectMaterial.dashSize,
objectMaterial.gapWidth,
objectMaterial.blending,
objectMaterial.blendSrc,
objectMaterial.blendDst,
objectMaterial.blendEquation,
objectMaterial.depthTest,
objectMaterial.depthFunc,
objectMaterial.depthWrite,
objectMaterial.polygonOffset,
objectMaterial.polygonOffsetFactor,
objectMaterial.polygonOffsetUnits,
objectMaterial.alphaTest,
objectMaterial.clippingPlanes,
objectMaterial.clipShadows,
objectMaterial.visible,
objectMaterial.overdraw,
objectMaterial.flatShading,
objectMaterial.bumpScale,
objectMaterial.normalScale,
objectMaterial.displacementScale,
objectMaterial.displacementBias,
objectMaterial.roughness,
objectMaterial.metalness,
objectMaterial.pointSize,
objectMaterial.pointSizeAttenuation,
objectMaterial.spriteRotation,
objectMaterial.envMapIntensity,
apiAlphaMap,
apiAoMap,
apiBumpMap,
apiDiffuseMap,
apiDisplacementMap,
apiEmissiveMap,
apiEnvironmentMap,
apiLightMap,
apiMetalnessMap,
apiNormalMap,
apiRoughnessMap,
apiSpecularMap,
objectMaterial.parentEntity
)
};
/**
* Raw Mesh API object - should always correspond with the Mesh Schema
* @param id
* @param meshType
* @param name
* @param vertices GameLib.D3.Vertex[]
* @param faces GameLib.D3.Face[]
* @param materials GameLib.D3.API.Material[]
* @param parentMesh
* @param parentScene
* @param skeleton
* @param skinIndices
* @param skinWeights
* @param position GameLib.API.Vector3
* @param quaternion GameLib.API.Quaternion
* @param rotation
* @param scale GameLib.API.Vector3
* @param up
* @param modelMatrix GameLib.API.Matrix4
* @param parentEntity
* @param renderOrder
* @param isBufferMesh
* @param useQuaternion (use quaternion property for rotation rather than rotation property)
* @constructor
*/
GameLib.D3.API.Mesh = function(
id,
meshType,
name,
vertices,
faces,
materials,
parentMesh,
parentScene,
skeleton,
skinIndices,
skinWeights,
position,
quaternion,
rotation,
scale,
up,
modelMatrix,
parentEntity,
renderOrder,
isBufferMesh,
useQuaternion,
visible
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(meshType)) {
meshType = GameLib.D3.Mesh.MESH_TYPE_NORMAL;
}
this.meshType = meshType;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Mesh (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(vertices)) {
vertices = [];
}
this.vertices = vertices;
if (GameLib.Utils.UndefinedOrNull(faces)) {
faces = [];
}
this.faces = faces;
if (GameLib.Utils.UndefinedOrNull(parentMesh)) {
parentMesh = null;
}
this.parentMesh = parentMesh;
if (GameLib.Utils.UndefinedOrNull(parentScene)) {
parentScene = null;
}
this.parentScene = parentScene;
if (GameLib.Utils.UndefinedOrNull(skeleton)) {
skeleton = null;
}
this.skeleton = skeleton;
if (GameLib.Utils.UndefinedOrNull(skinIndices)) {
skinIndices = [];
}
this.skinIndices = skinIndices;
if (GameLib.Utils.UndefinedOrNull(skinWeights)) {
skinWeights = [];
}
this.skinWeights = skinWeights;
if (GameLib.Utils.UndefinedOrNull(materials) || (materials instanceof Array && materials.length === 0)) {
materials = [new GameLib.D3.API.Material(null, GameLib.D3.Material.MATERIAL_TYPE_STANDARD, 'Material (' + this.name + ')')];
}
this.materials = materials;
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3(0,0,0);
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(quaternion)) {
quaternion = new GameLib.API.Quaternion();
}
this.quaternion = quaternion;
if (GameLib.Utils.UndefinedOrNull(rotation)) {
rotation = new GameLib.API.Vector3(0,0,0);
}
this.rotation = rotation;
if (GameLib.Utils.UndefinedOrNull(scale)) {
scale = new GameLib.API.Vector3(1,1,1);
}
this.scale = scale;
if (GameLib.Utils.UndefinedOrNull(up)) {
up = new GameLib.API.Vector3(0,1,0);
}
this.up = up;
if (GameLib.Utils.UndefinedOrNull(modelMatrix)) {
modelMatrix = new GameLib.API.Matrix4();
}
this.modelMatrix = modelMatrix;
if (GameLib.Utils.UndefinedOrNull(renderOrder)) {
renderOrder = 0;
}
this.renderOrder = renderOrder;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.Utils.UndefinedOrNull(isBufferMesh)) {
isBufferMesh = false;
}
this.isBufferMesh = isBufferMesh;
if (GameLib.Utils.UndefinedOrNull(useQuaternion)) {
useQuaternion = true;
}
this.useQuaternion = useQuaternion;
if (GameLib.Utils.UndefinedOrNull(visible)) {
visible = true;
}
this.visible = visible;
};
GameLib.D3.API.Mesh.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Mesh.prototype.constructor = GameLib.D3.API.Mesh;
/**
* Returns an API Mesh from an Object mesh
* @param objectMesh
* @constructor
*/
GameLib.D3.API.Mesh.FromObject = function (objectMesh){
var apiFaces = [];
if (objectMesh.faces) {
apiFaces = objectMesh.faces.map(
function(face) {
return GameLib.D3.API.Face.FromObject(face);
}
);
}
var apiSkeleton = null;
if (objectMesh.skeleton) {
apiSkeleton = GameLib.D3.API.Skeleton.FromObject(objectMesh.skeleton);
}
var apiMaterials = [];
if (objectMesh.materials) {
apiMaterials = objectMesh.materials.map(
function (objectMaterial) {
/**
* From blender we only get Ids to materials (strings)
*/
if (objectMaterial instanceof Object) {
return GameLib.D3.API.Material.FromObject(objectMaterial);
} else {
return objectMaterial
}
}
)
}
var apiVertices = [];
if (objectMesh.vertices) {
apiVertices = objectMesh.vertices.map(
function (objectVertex) {
return GameLib.D3.API.Vertex.FromObject(objectVertex);
}
)
}
var apiPosition = new GameLib.API.Vector3();
if (objectMesh.position) {
apiPosition = GameLib.API.Vector3.FromObject(objectMesh.position);
}
var apiRotation = new GameLib.API.Vector3();
if (objectMesh.rotation) {
apiRotation = GameLib.API.Vector3.FromObject(objectMesh.rotation);
}
var apiQuaternion = new GameLib.API.Quaternion();
if (objectMesh.quaternion) {
apiQuaternion = GameLib.API.Quaternion.FromObject(objectMesh.quaternion);
}
var apiScale = new GameLib.API.Vector3(1,1,1);
if (objectMesh.scale) {
apiScale = GameLib.API.Vector3.FromObject(objectMesh.scale);
}
var apiUp = new GameLib.API.Vector3(0,1,0);
if (objectMesh.up) {
apiUp = GameLib.API.Vector3.FromObject(objectMesh.up);
}
var apiModelMatrix = new GameLib.API.Matrix4();
if (objectMesh.modelMatrix) {
apiModelMatrix = GameLib.API.Matrix4.FromObject(objectMesh.modelMatrix);
}
return new GameLib.D3.API.Mesh(
objectMesh.id,
objectMesh.meshType,
objectMesh.name,
apiVertices,
apiFaces,
apiMaterials,
objectMesh.parentMesh,
objectMesh.parentScene,
apiSkeleton,
objectMesh.skinIndices,
objectMesh.skinWeights,
apiPosition,
apiQuaternion,
apiRotation,
apiScale,
apiUp,
apiModelMatrix,
objectMesh.parentEntity,
objectMesh.renderOrder,
objectMesh.isBufferMesh,
objectMesh.useQuaternion,
objectMesh.visible
);
};
/**
* Raw ParticleEngine API object - should always correspond with the ParticleEngine Schema
* @param id
* @param name
* @param position
* @param direction
* @param enabled
* @param templateParticle
* @param particlesPerSecond
* @param frequency
* @param elapsed
* @param camera
* @param pulse
* @param parentEntity
* @constructor
*/
GameLib.D3.API.ParticleEngine = function(
id,
name,
position,
direction,
enabled,
templateParticle,
particlesPerSecond,
frequency,
elapsed,
camera,
pulse,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'ParticleEngine (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3(0, 0, 0);
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(direction)) {
direction = new GameLib.API.Vector3(0, 1, 0);
}
this.direction = direction;
if (GameLib.Utils.UndefinedOrNull(enabled)) {
enabled = false;
}
this.enabled = enabled;
if (GameLib.Utils.UndefinedOrNull(templateParticle)) {
templateParticle = null;
}
this.templateParticle = templateParticle;
if (GameLib.Utils.UndefinedOrNull(particlesPerSecond)) {
particlesPerSecond = 1;
}
this.particlesPerSecond = particlesPerSecond;
if (GameLib.Utils.UndefinedOrNull(frequency)) {
frequency = Number(1 / Number(this.particlesPerSecond));
}
this.frequency = frequency;
if (GameLib.Utils.UndefinedOrNull(elapsed)) {
elapsed = 0;
}
this.elapsed = elapsed;
if (GameLib.Utils.UndefinedOrNull(camera)) {
camera = null;
}
this.camera = camera;
if (GameLib.Utils.UndefinedOrNull(pulse)) {
pulse = false;
}
this.pulse = pulse;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.ParticleEngine.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.ParticleEngine.prototype.constructor = GameLib.D3.API.ParticleEngine;
/**
* Creates an API ParticleEngine from an Object ParticleEngine
* @param objectParticleEngine
* @constructor
*/
GameLib.D3.API.ParticleEngine.FromObject = function(objectParticleEngine) {
var apiTemplateParticle = null;
if (objectParticleEngine.templateParticle) {
if (objectParticleEngine.templateParticle instanceof Object) {
apiTemplateParticle = GameLib.D3.API.Particle.FromObject(objectParticleEngine.templateParticle);
} else {
apiTemplateParticle = objectParticleEngine.templateParticle;
}
}
var apiCamera = null;
if (objectParticleEngine.camera) {
if (objectParticleEngine.camera instanceof Object) {
apiCamera = GameLib.D3.API.Camera.FromObject(objectParticleEngine.camera);
} else {
apiCamera = objectParticleEngine.camera;
}
}
var apiPosition = null;
if (objectParticleEngine.position) {
apiPosition = GameLib.API.Vector3.FromObject(objectParticleEngine.position);
}
var apiDirection = null;
if (objectParticleEngine.direction) {
apiDirection = GameLib.API.Vector3.FromObject(objectParticleEngine.direction);
}
return new GameLib.D3.API.ParticleEngine(
objectParticleEngine.id,
objectParticleEngine.name,
apiPosition,
apiDirection,
objectParticleEngine.enabled,
apiTemplateParticle,
objectParticleEngine.particlesPerSecond,
objectParticleEngine.frequency,
objectParticleEngine.elapsed,
apiCamera,
objectParticleEngine.pulse,
objectParticleEngine.parentEntity
);
};
/**
* Raw Particle API object - should always correspond with the Particle Schema
* @param id
* @param name
* @param lifeTime
* @param elapsed
* @param mesh
* @param opacityType
* @param opacityFactor
* @param positionOffsetType
* @param positionOffset
* @param positionOffsetFn
* @param directionType
* @param rotation
* @param scale
* @param direction
* @param directionFn
* @param speedType
* @param speed
* @param scaleFn
* @param scaleType
* @param rotationType
* @param rotationFn
* @param parentEngine
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Particle = function(
id,
name,
lifeTime,
elapsed,
mesh,
opacityType,
opacityFactor,
positionOffsetType,
positionOffset,
positionOffsetFn,
directionType,
direction,
directionFn,
speedType,
speed,
scaleType,
scale,
scaleFn,
rotationType,
rotation,
rotationFn,
parentEngine,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Particle (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(lifeTime)) {
lifeTime = 10;
}
this.lifeTime = lifeTime;
if (GameLib.Utils.UndefinedOrNull(elapsed)) {
elapsed = 0;
}
this.elapsed = elapsed;
if (GameLib.Utils.UndefinedOrNull(mesh)) {
mesh = null;
}
this.mesh = mesh;
if (GameLib.Utils.UndefinedOrNull(opacityType)) {
opacityType = GameLib.D3.Particle.OPACITY_TYPE_CONSTANT;
}
this.opacityType = opacityType;
if (GameLib.Utils.UndefinedOrNull(opacityFactor)) {
opacityFactor = 0.01;
}
this.opacityFactor = opacityFactor;
if (GameLib.Utils.UndefinedOrNull(positionOffsetType)) {
positionOffsetType = GameLib.D3.Particle.POSITION_OFFSET_TYPE_CONSTANT;
}
this.positionOffsetType = positionOffsetType;
if (GameLib.Utils.UndefinedOrNull(positionOffset)) {
positionOffset = new GameLib.API.Vector3(0, 0, 0);
}
this.positionOffset = positionOffset;
if (GameLib.Utils.UndefinedOrNull(positionOffsetFn)) {
positionOffsetFn = '//@ sourceURL=positionOffsetFn.js';
}
this.positionOffsetFn = positionOffsetFn;
if (GameLib.Utils.UndefinedOrNull(directionType)) {
directionType = GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT;
}
this.directionType = directionType;
if (GameLib.Utils.UndefinedOrNull(direction)) {
direction = new GameLib.API.Vector3(0, 1, 0);
}
this.direction = direction;
if (GameLib.Utils.UndefinedOrNull(directionFn)) {
directionFn = '//@ sourceURL=directionFn.js';
}
this.directionFn = directionFn;
if (GameLib.Utils.UndefinedOrNull(speedType)) {
speedType = GameLib.D3.Particle.SPEED_TYPE_CONSTANT;
}
this.speedType = speedType;
if (GameLib.Utils.UndefinedOrNull(speed)) {
speed = 1;
}
this.speed = speed;
if (GameLib.Utils.UndefinedOrNull(scaleType)) {
scaleType = GameLib.D3.Particle.SCALE_TYPE_CONSTANT;
}
this.scaleType = scaleType;
if (GameLib.Utils.UndefinedOrNull(scale)) {
scale = new GameLib.API.Vector3(1, 1, 1);
}
this.scale = scale;
if (GameLib.Utils.UndefinedOrNull(scaleFn)) {
scaleFn = '//@ sourceURL=scaleFn.js';
}
this.scaleFn = scaleFn;
if (GameLib.Utils.UndefinedOrNull(rotationType)) {
rotationType = GameLib.D3.Particle.ROTATION_TYPE_CONSTANT;
}
this.rotationType = rotationType;
if (GameLib.Utils.UndefinedOrNull(rotation)) {
rotation = new GameLib.API.Vector3(0, 0, 0);
}
this.rotation = rotation;
if (GameLib.Utils.UndefinedOrNull(rotationFn)) {
rotationFn = '//@ sourceURL=rotationFn.js';
}
this.rotationFn = rotationFn;
if (GameLib.Utils.UndefinedOrNull(parentEngine)) {
parentEngine = null;
}
this.parentEngine = parentEngine;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Particle.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Particle.prototype.constructor = GameLib.D3.API.Particle;
/**
* Creates an API Particle from an Object Particle
* @param objectParticle
* @constructor
*/
GameLib.D3.API.Particle.FromObject = function(objectParticle) {
var apiMesh = null;
if (objectParticle.mesh) {
if (objectParticle.mesh instanceof Object) {
apiMesh = GameLib.D3.API.Mesh.FromObject(objectParticle.mesh);
} else {
apiMesh = objectParticle.mesh;
}
}
return new GameLib.D3.API.Particle(
objectParticle.id,
objectParticle.name,
objectParticle.lifeTime,
objectParticle.elapsed,
apiMesh,
objectParticle.opacityType,
objectParticle.opacityFactor,
objectParticle.positionOffsetType,
GameLib.API.Vector3.FromObject(objectParticle.positionOffset),
objectParticle.positionOffsetFn,
objectParticle.directionType,
GameLib.API.Vector3.FromObject(objectParticle.direction),
objectParticle.directionFn,
objectParticle.speedType,
objectParticle.speed,
objectParticle.scaleType,
GameLib.API.Vector3.FromObject(objectParticle.scale),
objectParticle.scaleFn,
objectParticle.rotationType,
GameLib.API.Vector3.FromObject(objectParticle.rotation),
objectParticle.rotationFn,
objectParticle.parentEngine,
objectParticle.parentEntity
);
};
/**
* This component renders a scene
* @param id String
* @param name String
* @param passType
* @param camera
* @param scene
* @param renderToScreen
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Pass = function (
id,
name,
passType,
camera,
scene,
renderToScreen,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Pass (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(passType)) {
passType = GameLib.D3.Pass.PASS_TYPE_RENDER;
}
this.passType = passType;
if (GameLib.Utils.UndefinedOrNull(camera)) {
camera = null;
}
this.camera = camera;
if (GameLib.Utils.UndefinedOrNull(scene)) {
scene = null;
}
this.scene = scene;
if (GameLib.Utils.UndefinedOrNull(renderToScreen)) {
if (this.passType === GameLib.D3.Pass.PASS_TYPE_RENDER) {
renderToScreen = false;
} else if (GameLib.D3.Pass.PASS_TYPE_COPY_SHADER) {
renderToScreen = true;
} else {
console.warn('Unsupported Render Pass Type : ' + this.passType);
throw new Error('Unsupported Render Pass Type : ' + this.passType);
}
}
this.renderToScreen = renderToScreen;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Pass.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Pass.prototype.constructor = GameLib.D3.API.Pass;
/**
* Object to GameLib.D3.API.Pass
* @param objectComponent
* @constructor
*/
GameLib.D3.API.Pass.FromObject = function(objectComponent) {
return new GameLib.D3.API.Pass(
objectComponent.id,
objectComponent.name,
objectComponent.passType,
objectComponent.camera,
objectComponent.scene,
objectComponent.renderToScreen,
objectComponent.parentEntity
);
};
/**
* This component makes the parentEntity (ex. car) follow the path provided by the spline
* @param id String
* @param name String
* @param spline GameLib.D3.API.Spline
* @param mesh GameLib.D3.API.Mesh
* @param raytraceMesh GameLib.D3.API.Mesh
* @param accelleration Number
* @param maxSpeed Number
* @param baseOffset GameLib.API.Vector
* @param maxOffset GameLib.API.Vector
* @param steeringSpeed Number
* @param targetOffset GameLib.API.Vector3
* @param currentOffset GameLib.API.Vector3
* @param currentPathValue Number
* @param currentSpeed Number
* @param direction Number
* @param raycaster GameLib.D3.Raycaster
* @param currentPosition GameLib.API.Vector3
* @param futurePosition GameLib.API.Vector3
* @param up GameLib.API.Vector3
* @param rotationMatrix GameLib.API.Matrix4
* @param rotationVector GameLib.API.Quaternion
* @param parentEntity
* @constructor
*/
GameLib.D3.API.PathFollowing = function (
id,
name,
spline,
mesh,
raytraceMesh,
accelleration,
maxSpeed,
baseOffset,
maxOffset,
steeringSpeed,
targetOffset,
currentOffset,
currentPathValue,
currentSpeed,
direction,
raycaster,
currentPosition,
futurePosition,
up,
rotationMatrix,
rotationVector,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = this.constructor.name;
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(spline)) {
spline = null;
}
this.spline = spline;
if (GameLib.Utils.UndefinedOrNull(mesh)) {
mesh = null;
}
this.mesh = mesh;
if (GameLib.Utils.UndefinedOrNull(raytraceMesh)) {
raytraceMesh = null;
}
this.raytraceMesh = raytraceMesh;
if (GameLib.Utils.UndefinedOrNull(maxSpeed)) {
maxSpeed = 0.03;
}
this.maxSpeed = maxSpeed;
if (GameLib.Utils.UndefinedOrNull(accelleration)) {
accelleration = 0.1;
}
this.accelleration = accelleration;
if (GameLib.Utils.UndefinedOrNull(baseOffset)) {
baseOffset = new GameLib.API.Vector3();
}
this.baseOffset = baseOffset;
if (GameLib.Utils.UndefinedOrNull(maxOffset)) {
maxOffset = new GameLib.API.Vector3();
}
this.maxOffset = maxOffset;
if (GameLib.Utils.UndefinedOrNull(steeringSpeed)) {
steeringSpeed = 1.0;
}
this.steeringSpeed = steeringSpeed;
if (GameLib.Utils.UndefinedOrNull(targetOffset)) {
targetOffset = new GameLib.API.Vector3();
}
this.targetOffset = targetOffset;
if (GameLib.Utils.UndefinedOrNull(currentOffset)) {
currentOffset = new GameLib.API.Vector3();
}
this.currentOffset = currentOffset;
if (GameLib.Utils.UndefinedOrNull(currentPathValue)) {
currentPathValue = 0;
}
this.currentPathValue = currentPathValue;
if (GameLib.Utils.UndefinedOrNull(currentSpeed)) {
currentSpeed = 0;
}
this.currentSpeed = currentSpeed;
if (GameLib.Utils.UndefinedOrNull(direction)) {
direction = 1;
}
this.direction = direction;
if (GameLib.Utils.UndefinedOrNull(raycaster)) {
raycaster = new GameLib.D3.API.Raycaster();
}
this.raycaster = raycaster;
if (GameLib.Utils.UndefinedOrNull(currentPosition)) {
currentPosition = new GameLib.API.Vector3();
}
this.currentPosition = currentPosition;
if (GameLib.Utils.UndefinedOrNull(futurePosition)) {
futurePosition = new GameLib.API.Vector3();
}
this.futurePosition = futurePosition;
if(GameLib.Utils.UndefinedOrNull(up)) {
up = new GameLib.API.Vector3(0, 1, 0);
}
this.up = up;
if (GameLib.Utils.UndefinedOrNull(rotationMatrix)) {
rotationMatrix = new GameLib.API.Matrix4();
}
this.rotationMatrix = rotationMatrix;
if (GameLib.Utils.UndefinedOrNull(rotationVector)) {
rotationVector = new GameLib.API.Quaternion();
}
this.rotationVector = rotationVector;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.PathFollowing.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.PathFollowing.prototype.constructor = GameLib.D3.API.PathFollowing;
/**
* Returns an API path following component from an Object path following component
* @param objectComponent
* @constructor
*/
GameLib.D3.API.PathFollowing.FromObject = function(objectComponent) {
var apiRaycaster = null;
if (objectComponent.raycaster) {
apiRaycaster = GameLib.D3.API.Raycaster.FromObject(objectComponent.raycaster);
}
return new GameLib.D3.API.PathFollowing(
objectComponent.id,
objectComponent.name,
objectComponent.spline,
objectComponent.mesh,
objectComponent.raytraceMesh,
objectComponent.accelleration,
objectComponent.maxSpeed,
GameLib.API.Vector3.FromObject(objectComponent.baseOffset),
GameLib.API.Vector3.FromObject(objectComponent.maxOffset),
objectComponent.steeringSpeed,
GameLib.API.Vector3.FromObject(objectComponent.targetOffset),
GameLib.API.Vector3.FromObject(objectComponent.currentOffset),
objectComponent.currentPathValue,
objectComponent.currentSpeed,
objectComponent.direction,
apiRaycaster,
GameLib.API.Vector3.FromObject(objectComponent.currentPosition),
GameLib.API.Vector3.FromObject(objectComponent.futurePosition),
GameLib.API.Vector3.FromObject(objectComponent.up),
GameLib.API.Matrix4.FromObject(objectComponent.rotationMatrix),
GameLib.API.Quaternion.FromObject(objectComponent.rotationVector),
objectComponent.parentEntity
);
};
/**
* Raw World API object - should always correspond with the World Schema
* @param id
* @param name
* @param gravity
* @param broadphase
* @param solver
* @param rigidBodies
* @param contactMaterials
* @param allowSleep
* @param parentEntity
* @constructor
*/
GameLib.D3.API.PhysicsWorld = function(
id,
name,
gravity,
broadphase,
solver,
rigidBodies,
contactMaterials,
allowSleep,
defaultContactMaterial,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Physics World (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(gravity)) {
gravity = new GameLib.API.Vector3(0, -9.81, 0);
}
this.gravity = gravity;
if (GameLib.Utils.UndefinedOrNull(broadphase)) {
broadphase = new GameLib.D3.API.Broadphase(
null,
'Broadphase (Physics World ' + this.id + ')'
);
}
this.broadphase = broadphase;
if (GameLib.Utils.UndefinedOrNull(solver)) {
solver = new GameLib.D3.API.Solver(
null,
'Solver (Physics World ' + this.id + ')'
)
}
this.solver = solver;
if (GameLib.Utils.UndefinedOrNull(rigidBodies)) {
rigidBodies = [];
}
this.rigidBodies = rigidBodies;
if (GameLib.Utils.UndefinedOrNull(contactMaterials)) {
contactMaterials = [];
}
this.contactMaterials = contactMaterials;
if (GameLib.Utils.UndefinedOrNull(allowSleep)) {
allowSleep = true;
}
this.allowSleep = allowSleep;
if (GameLib.Utils.UndefinedOrNull(defaultContactMaterial)) {
defaultContactMaterial = new GameLib.D3.API.FrictionContactMaterial(
null,
'Default Contact Material (Physics World ' + this.id + ')'
);
}
this.defaultContactMaterial = defaultContactMaterial;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.PhysicsWorld.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.PhysicsWorld.prototype.constructor = GameLib.D3.API.PhysicsWorld;
/**
* Creates an API World from an Object World
* @param objectWorld
* @constructor
*/
GameLib.D3.API.PhysicsWorld.FromObject = function(objectWorld) {
return new GameLib.D3.API.PhysicsWorld(
objectWorld.id,
objectWorld.name,
GameLib.API.Vector3.FromObject(objectWorld.gravity),
objectWorld.broadphase,
objectWorld.solver,
objectWorld.rigidBodies,
objectWorld.contactMaterials,
objectWorld.allowSleep,
objectWorld.defaultContactMaterial,
objectWorld.parentEntity
);
};
/**
* Raw RaycastVehicle API object - should always correspond with the RaycastVehicle Schema
* @param id
* @param name
* @param chassis
* @param wheels
* @param raycastWheels
* @param parentWorld
* @param parentEntity
* @constructor
*/
GameLib.D3.API.RaycastVehicle = function(
id,
name,
chassis,
wheels,
raycastWheels,
parentWorld,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'RaycastVehicle (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(chassis)) {
chassis = null;
}
this.chassis = chassis;
if (GameLib.Utils.UndefinedOrNull(wheels)) {
wheels = [];
}
this.wheels = wheels;
if (GameLib.Utils.UndefinedOrNull(raycastWheels)) {
raycastWheels = [];
}
this.raycastWheels = raycastWheels;
if (GameLib.Utils.UndefinedOrNull(parentWorld)) {
parentWorld = null;
}
this.parentWorld = parentWorld;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.RaycastVehicle.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.RaycastVehicle.prototype.constructor = GameLib.D3.API.RaycastVehicle;
/**
* Creates an API RaycastVehicle from an Object RaycastVehicle
* @param objectRaycastVehicle
* @constructor
*/
GameLib.D3.API.RaycastVehicle.FromObject = function(objectRaycastVehicle) {
return new GameLib.D3.API.RaycastVehicle(
objectRaycastVehicle.id,
objectRaycastVehicle.name,
objectRaycastVehicle.chassis,
objectRaycastVehicle.wheels,
objectRaycastVehicle.raycastWheels,
objectRaycastVehicle.parentWorld,
objectRaycastVehicle.parentEntity
);
};
/**
* Raw RaycastWheel API object - should always correspond with the RaycastWheel Schema
* @param id
* @param name
* @param radius
* @param directionLocal
* @param suspensionStiffness
* @param suspensionRestLength
* @param frictionSlip
* @param dampingRelaxation
* @param dampingCompression
* @param maxSuspensionForce
* @param rollInfluence
* @param axleLocal
* @param chassisConnectionPointLocal
* @param maxSuspensionTravel
* @param customSlidingRotationalSpeed
* @param useCustomSlidingRotationalSpeed
* @param parentEntity
* @param parentMesh
* @constructor
*/
GameLib.D3.API.RaycastWheel = function(
id,
name,
radius,
directionLocal,
suspensionStiffness,
suspensionRestLength,
frictionSlip,
dampingRelaxation,
dampingCompression,
maxSuspensionForce,
rollInfluence,
axleLocal,
chassisConnectionPointLocal,
maxSuspensionTravel,
customSlidingRotationalSpeed,
useCustomSlidingRotationalSpeed,
parentEntity,
parentMesh
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'RaycastWheel (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(radius)) {
radius = 0.5;
}
this.radius = radius;
if (GameLib.Utils.UndefinedOrNull(directionLocal)) {
directionLocal = new GameLib.API.Vector3(0, 0, -1);
}
this.directionLocal = directionLocal;
if (GameLib.Utils.UndefinedOrNull(suspensionStiffness)) {
suspensionStiffness = 30;
}
this.suspensionStiffness = suspensionStiffness;
if (GameLib.Utils.UndefinedOrNull(suspensionRestLength)) {
suspensionRestLength = 0.3;
}
this.suspensionRestLength = suspensionRestLength;
if (GameLib.Utils.UndefinedOrNull(frictionSlip)) {
frictionSlip = 5;
}
this.frictionSlip = frictionSlip;
if (GameLib.Utils.UndefinedOrNull(dampingRelaxation)) {
dampingRelaxation = 2.3;
}
this.dampingRelaxation = dampingRelaxation;
if (GameLib.Utils.UndefinedOrNull(dampingCompression)) {
dampingCompression = 4.4;
}
this.dampingCompression = dampingCompression;
if (GameLib.Utils.UndefinedOrNull(maxSuspensionForce)) {
maxSuspensionForce = 100000;
}
this.maxSuspensionForce = maxSuspensionForce;
if (GameLib.Utils.UndefinedOrNull(rollInfluence)) {
rollInfluence = 0.01;
}
this.rollInfluence = rollInfluence;
if (GameLib.Utils.UndefinedOrNull(axleLocal)) {
axleLocal = new GameLib.API.Vector3(0, 1, 0);
}
this.axleLocal = axleLocal;
if (GameLib.Utils.UndefinedOrNull(chassisConnectionPointLocal)) {
chassisConnectionPointLocal = new GameLib.API.Vector3(1, 1, 0);
}
this.chassisConnectionPointLocal = chassisConnectionPointLocal;
if (GameLib.Utils.UndefinedOrNull(maxSuspensionTravel)) {
maxSuspensionTravel = 0.3;
}
this.maxSuspensionTravel = maxSuspensionTravel;
if (GameLib.Utils.UndefinedOrNull(customSlidingRotationalSpeed)) {
customSlidingRotationalSpeed = -30;
}
this.customSlidingRotationalSpeed = customSlidingRotationalSpeed;
if (GameLib.Utils.UndefinedOrNull(useCustomSlidingRotationalSpeed)) {
useCustomSlidingRotationalSpeed = true;
}
this.useCustomSlidingRotationalSpeed = useCustomSlidingRotationalSpeed;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.Utils.UndefinedOrNull(parentMesh)) {
parentMesh = null;
}
this.parentMesh = parentMesh;
};
GameLib.D3.API.RaycastWheel.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.RaycastWheel.prototype.constructor = GameLib.D3.API.RaycastWheel;
/**
* Creates an API RaycastWheel from an Object RaycastWheel
* @param objectRaycastWheel
* @constructor
*/
GameLib.D3.API.RaycastWheel.FromObject = function(objectRaycastWheel) {
return new GameLib.D3.API.RaycastWheel(
objectRaycastWheel.id,
objectRaycastWheel.name,
objectRaycastWheel.radius,
objectRaycastWheel.directionLocal,
objectRaycastWheel.suspensionStiffness,
objectRaycastWheel.suspensionRestLength,
objectRaycastWheel.frictionSlip,
objectRaycastWheel.dampingRelaxation,
objectRaycastWheel.dampingCompression,
objectRaycastWheel.maxSuspensionForce,
objectRaycastWheel.rollInfluence,
objectRaycastWheel.axleLocal,
objectRaycastWheel.chassisConnectionPointLocal,
objectRaycastWheel.maxSuspensionTravel,
objectRaycastWheel.customSlidingRotationalSpeed,
objectRaycastWheel.useCustomSlidingRotationalSpeed,
objectRaycastWheel.parentEntity,
objectRaycastWheel.parentMesh
);
};
/**
* Raycaster for GameLib.D3
* @param id
* @param name
* @param position GameLib.API.Vector3
* @param direction GameLib.API.Vector3
* @constructor
*/
GameLib.D3.API.Raycaster = function(
id,
name,
position,
direction
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Raycaster (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3();
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(direction)) {
direction = new GameLib.API.Vector3(0, -1, 0);
}
this.direction = direction;
};
GameLib.D3.API.Raycaster.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Raycaster.prototype.constructor = GameLib.D3.API.Raycaster;
/**
* Returns an API raycaster from an Object raycaster
* @param objectRaycaster
* @constructor
*/
GameLib.D3.API.Raycaster.FromObject = function(objectRaycaster) {
return new GameLib.D3.API.Raycaster(
objectRaycaster.id,
objectRaycaster.name,
GameLib.API.Vector3.FromObject(objectRaycaster.position),
GameLib.API.Vector3.FromObject(objectRaycaster.direction)
);
};
/**
* This component renders a scene
* @param id String
* @param name String
* @param width
* @param height
* @param minFilter
* @param magFilter
* @param format
* @param stencilBuffer
* @param texture
* @param parentEntity
* @constructor
*/
GameLib.D3.API.RenderTarget = function (
id,
name,
width,
height,
stencilBuffer,
texture,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Render Target (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(width)) {
width = 800;
}
this.width = width;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 600;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(stencilBuffer)) {
stencilBuffer = false;
}
this.stencilBuffer = stencilBuffer;
if (GameLib.Utils.UndefinedOrNull(texture)) {
texture = null;
}
this.texture = texture;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.RenderTarget.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.RenderTarget.prototype.constructor = GameLib.D3.API.RenderTarget;
/**
* Object to GameLib.D3.API.RenderTarget
* @param objectComponent
* @constructor
*/
GameLib.D3.API.RenderTarget.FromObject = function(objectComponent) {
return new GameLib.D3.API.RenderTarget(
objectComponent.id,
objectComponent.name,
objectComponent.width,
objectComponent.height,
objectComponent.stencilBuffer,
objectComponent.texture,
objectComponent.parentEntity
);
};
/**
* This component renders a scene
* @param id String
* @param name String
* @param autoClear bool
* @param localClipping
* @param width
* @param height
* @param domElement
* @param clearColor
* @param camera
* @param scenes
* @param viewports
* @param parentEntity
* @param preserveDrawingBuffer
* @param clippingPlanes
* @param bufferScene
* @param bufferCamera
* @param renderTarget
* @param defaultScene
* @constructor
*/
GameLib.D3.API.Renderer = function (
id,
name,
autoClear,
localClipping,
width,
height,
preserveDrawingBuffer,
domElement,
clearColor,
camera,
scenes,
viewports,
clippingPlanes,
bufferScene,
bufferCamera,
renderTarget,
defaultScene,
sortObjects,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = "Renderer (" + this.id + ")";
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(autoClear)) {
autoClear = true;
}
this.autoClear = autoClear;
if (GameLib.Utils.UndefinedOrNull(localClipping)) {
localClipping = false;
if (clippingPlanes && clippingPlanes.length > 0) {
localClipping = true;
}
}
this.localClipping = localClipping;
if (GameLib.Utils.UndefinedOrNull(width)) {
width = 800;
}
this.width = width;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 600;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(preserveDrawingBuffer)) {
preserveDrawingBuffer = false;
}
this.preserveDrawingBuffer = preserveDrawingBuffer;
if (GameLib.Utils.UndefinedOrNull(domElement)) {
domElement = null;
}
this.domElement = domElement;
if (GameLib.Utils.UndefinedOrNull(clearColor)) {
clearColor = new GameLib.API.Color(0.11, 0.11, 0.11);
}
this.clearColor = clearColor;
if (GameLib.Utils.UndefinedOrNull(camera)) {
camera = null;
}
this.camera = camera;
if (GameLib.Utils.UndefinedOrNull(scenes)) {
scenes = [];
}
this.scenes = scenes;
if (GameLib.Utils.UndefinedOrNull(viewports)) {
viewports = [];
}
this.viewports = viewports;
if (GameLib.Utils.UndefinedOrNull(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(defaultScene)) {
defaultScene = null;
}
this.defaultScene = defaultScene;
if (GameLib.Utils.UndefinedOrNull(sortObjects)) {
sortObjects = true;
}
this.sortObjects = sortObjects;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Renderer.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Renderer.prototype.constructor = GameLib.D3.API.Renderer;
/**
* Object to GameLib.D3.API.Renderer
* @param objectComponent
* @constructor
*/
GameLib.D3.API.Renderer.FromObject = function(objectComponent) {
return new GameLib.D3.API.Renderer(
objectComponent.id,
objectComponent.name,
objectComponent.autoClear,
objectComponent.localClipping,
objectComponent.width,
objectComponent.height,
objectComponent.preserveDrawingBuffer,
objectComponent.domElement,
objectComponent.clearColor,
objectComponent.camera,
objectComponent.scenes,
objectComponent.viewports,
objectComponent.clippingPlanes,
objectComponent.bufferScene,
objectComponent.bufferCamera,
objectComponent.renderTarget,
objectComponent.defaultScene,
objectComponent.sortObjects,
objectComponent.parentEntity
);
};
/**
* Raw RigidBody API object - should always correspond with the RigidBody Schema
* @param id
* @param name
* @param mass
* @param friction
* @param position
* @param quaternion
* @param velocity
* @param angularVelocity
* @param linearDamping
* @param angularDamping
* @param allowSleep
* @param sleepSpeedLimit
* @param sleepTimeLimit
* @param collisionFilterGroup
* @param collisionFilterMask
* @param fixedRotation
* @param shapes
* @param kinematic
* @param parentMesh
* @param parentWorld
* @param parentEntity
* @constructor
*/
GameLib.D3.API.RigidBody = function(
id,
name,
mass,
friction,
position,
quaternion,
velocity,
angularVelocity,
linearDamping,
angularDamping,
allowSleep,
sleepSpeedLimit,
sleepTimeLimit,
collisionFilterGroup,
collisionFilterMask,
fixedRotation,
shapes,
kinematic,
parentMesh,
parentWorld,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'RigidBody (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(mass)) {
mass = 0;
}
this.mass = mass;
if (GameLib.Utils.UndefinedOrNull(friction)) {
friction = 5;
}
this.friction = friction;
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3(0,0,0);
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(quaternion)) {
quaternion = new GameLib.API.Quaternion();
}
this.quaternion = quaternion;
if (GameLib.Utils.UndefinedOrNull(velocity)) {
velocity = new GameLib.API.Vector3();
}
this.velocity = velocity;
if (GameLib.Utils.UndefinedOrNull(angularVelocity)) {
angularVelocity = new GameLib.API.Vector3();
}
this.angularVelocity = angularVelocity;
if (GameLib.Utils.UndefinedOrNull(linearDamping)) {
linearDamping = 0.01;
}
this.linearDamping = linearDamping;
if (GameLib.Utils.UndefinedOrNull(angularDamping)) {
angularDamping = 0.01;
}
this.angularDamping = angularDamping;
if (GameLib.Utils.UndefinedOrNull(allowSleep)) {
allowSleep = true;
}
this.allowSleep = allowSleep;
if (GameLib.Utils.UndefinedOrNull(sleepSpeedLimit)) {
sleepSpeedLimit = 0.1;
}
this.sleepSpeedLimit = sleepSpeedLimit;
if (GameLib.Utils.UndefinedOrNull(sleepTimeLimit)) {
sleepTimeLimit = 1.0;
}
this.sleepTimeLimit = sleepTimeLimit;
if (GameLib.Utils.UndefinedOrNull(collisionFilterGroup)) {
collisionFilterGroup = 1;
}
this.collisionFilterGroup = collisionFilterGroup;
if (GameLib.Utils.UndefinedOrNull(collisionFilterMask)) {
collisionFilterMask = 1;
}
this.collisionFilterMask = collisionFilterMask;
if (GameLib.Utils.UndefinedOrNull(fixedRotation)) {
fixedRotation = false;
}
this.fixedRotation = fixedRotation;
if (GameLib.Utils.UndefinedOrNull(shapes)) {
shapes = [];
}
this.shapes = shapes;
if (GameLib.Utils.UndefinedOrNull(kinematic)) {
kinematic = false;
}
this.kinematic = kinematic;
if (GameLib.Utils.UndefinedOrNull(parentMesh)) {
parentMesh = null;
}
this.parentMesh = parentMesh;
if (GameLib.Utils.UndefinedOrNull(parentWorld)) {
parentWorld = null;
}
this.parentWorld = parentWorld;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.RigidBody.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.RigidBody.prototype.constructor = GameLib.D3.API.RigidBody;
/**
* Creates an API RigidBody from an Object RigidBody
* @param objectRigidBody
* @constructor
*/
GameLib.D3.API.RigidBody.FromObject = function(objectRigidBody) {
return new GameLib.D3.API.RigidBody(
objectRigidBody.id,
objectRigidBody.name,
objectRigidBody.mass,
objectRigidBody.friction,
objectRigidBody.position,
objectRigidBody.quaternion,
objectRigidBody.velocity,
objectRigidBody.angularVelocity,
objectRigidBody.linearDamping,
objectRigidBody.angularDamping,
objectRigidBody.allowSleep,
objectRigidBody.sleepSpeedLimit,
objectRigidBody.sleepTimeLimit,
objectRigidBody.collisionFilterGroup,
objectRigidBody.collisionFilterMask,
objectRigidBody.fixedRotation,
objectRigidBody.shapes,
objectRigidBody.kinematic,
objectRigidBody.parentMesh,
objectRigidBody.parentWorld,
objectRigidBody.parentEntity
);
};
/**
* Raw Scene API object - should always correspond with the Scene Schema
* @param id String
* @param name String
* @param meshes [GameLib.D3.API.Mesh]
* @param lights [GameLib.D3.API.Light]
* @param textures [GameLib.D3.API.Texture]
* @param materials [GameLib.D3.API.Material]
* @param images
* @param fog
* @param renderCamera - this is a camera which takes precedence over the renderer camera at time of render
* @param showGrid
* @param showAxis
* @param gridSize
* @param gridColor
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Scene = function(
id,
name,
meshes,
lights,
textures,
materials,
images,
fog,
renderCamera,
showGrid,
showAxis,
gridSize,
gridColor,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Scene (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(meshes)) {
meshes = [];
}
this.meshes = meshes;
if (GameLib.Utils.UndefinedOrNull(lights)) {
lights = [];
}
this.lights = lights;
if (GameLib.Utils.UndefinedOrNull(textures)) {
textures = [];
}
this.textures = textures;
if (GameLib.Utils.UndefinedOrNull(materials)) {
materials = [];
}
this.materials = materials;
if (GameLib.Utils.UndefinedOrNull(images)) {
images = [];
}
this.images = images;
if (GameLib.Utils.UndefinedOrNull(fog)) {
fog = null;
}
this.fog = fog;
if (GameLib.Utils.UndefinedOrNull(renderCamera)) {
renderCamera = null;
}
this.renderCamera = renderCamera;
if (GameLib.Utils.UndefinedOrNull(showGrid)) {
showGrid = true;
}
this.showGrid = showGrid;
if (GameLib.Utils.UndefinedOrNull(showAxis)) {
showAxis = true;
}
this.showAxis = showAxis;
if (GameLib.Utils.UndefinedOrNull(gridSize)) {
gridSize = 10;
}
this.gridSize = gridSize;
if (GameLib.Utils.UndefinedOrNull(gridColor)) {
gridColor = new GameLib.API.Color(0.1, 0.1, 0.1);
}
this.gridColor = gridColor;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Scene.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Scene.prototype.constructor = GameLib.D3.API.Scene;
/**
* Returns an API scene from an Object scene
* @param objectScene
* @constructor
*/
GameLib.D3.API.Scene.FromObject = function(objectScene) {
var apiMeshes = [];
var apiLights = [];
var apiTextures = [];
var apiMaterials = [];
var apiImages = [];
if (objectScene.meshes) {
apiMeshes = objectScene.meshes.map(
function(objectMesh) {
if (objectMesh instanceof Object){
return GameLib.D3.API.Mesh.FromObject(objectMesh);
} else {
return objectMesh;
}
}
)
}
if (objectScene.lights) {
apiLights = objectScene.lights.map(
function(objectLight) {
if (objectLight instanceof Object) {
return GameLib.D3.API.Light.FromObject(objectLight);
} else {
return objectLight;
}
}
)
}
if (objectScene.textures) {
apiTextures = objectScene.textures.map(
function(objectTexture) {
if (objectTexture instanceof Object) {
return GameLib.D3.API.Texture.FromObject(objectTexture)
} else {
return objectTexture;
}
}
)
}
if (objectScene.materials) {
apiMaterials = objectScene.materials.map(
function(objectMaterial) {
if (objectMaterial instanceof Object) {
return GameLib.D3.API.Material.FromObject(objectMaterial)
} else {
return objectMaterial;
}
}
)
}
if (objectScene.images) {
apiImages = objectScene.images.map(
function(objectImage) {
if (objectImage instanceof Object) {
return GameLib.D3.API.Image.FromObject(objectImage)
} else {
return objectImage;
}
}
)
}
return new GameLib.D3.API.Scene(
objectScene.id,
objectScene.name,
apiMeshes,
apiLights,
apiTextures,
apiMaterials,
apiImages,
objectScene.fog,
objectScene.renderCamera,
objectScene.showGrid,
objectScene.showAxis,
objectScene.gridSize,
GameLib.API.Color.FromObject(objectScene.gridColor),
objectScene.parentEntity
);
};
/**
* Raw Shape API object - should always correspond with the Shape Schema
* @param id
* @param name
* @param boundingSphereRadius
* @param collisionResponse
* @param frictionMaterial
* @param parentMesh
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Shape = function(
id,
name,
boundingSphereRadius,
collisionResponse,
frictionMaterial,
parentMesh,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Shape (' + this.id + ')';
if (this instanceof GameLib.D3.Shape.ConvexHull) {
name = 'Shape Convex Hull (' + this.id + ')';
}
if (this instanceof GameLib.D3.Shape.ConvexHull.Cylinder) {
name = 'Shape Convex Hull Cylinder (' + this.id + ')';
}
if (this instanceof GameLib.D3.Shape.HeightMap) {
name = 'Shape Heightmap (' + this.id + ')';
}
if (this instanceof GameLib.D3.Shape.Box) {
name = 'Shape Box (' + this.id + ')';
}
if (this instanceof GameLib.D3.Shape.Plane) {
name = 'Shape Plane (' + this.id + ')';
}
if (this instanceof GameLib.D3.Shape.Sphere) {
name = 'Shape Sphere (' + this.id + ')';
}
if (this instanceof GameLib.D3.Shape.TriMesh) {
name = 'Shape TriMesh (' + this.id + ')';
}
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(boundingSphereRadius)) {
boundingSphereRadius = 0;
}
this.boundingSphereRadius = boundingSphereRadius;
if (GameLib.Utils.UndefinedOrNull(collisionResponse)) {
collisionResponse = true;
}
this.collisionResponse = collisionResponse;
if (GameLib.Utils.UndefinedOrNull(frictionMaterial)) {
frictionMaterial = null;
}
this.frictionMaterial = frictionMaterial;
if (GameLib.Utils.UndefinedOrNull(parentMesh)) {
parentMesh = null;
}
this.parentMesh = parentMesh;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Shape.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Shape.prototype.constructor = GameLib.D3.API.Shape;
/**
* Creates an API Shape from an Object Shape
* @param objectShape
* @constructor
*/
GameLib.D3.API.Shape.FromObject = function(objectShape) {
return new GameLib.D3.API.Shape(
objectShape.id,
objectShape.name,
objectShape.boundingSphereRadius,
objectShape.collisionResponse,
objectShape.frictionMaterial,
objectShape.parentMesh,
objectShape.parentEntity
);
};
/**
* API Skeleton
* @param id
* @param name
* @param bones GameLib.D3.API.Bone[]
* @param boneInverses GameLib.API.Matrix4[]
* @param useVertexTexture boolean
* @param boneTextureWidth Number
* @param boneTextureHeight Number
* @param boneMatrices GameLib.API.Matrix4[]
* @param boneTexture null (not implemented)
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Skeleton = function (
id,
name,
bones,
boneInverses,
useVertexTexture,
boneTextureWidth,
boneTextureHeight,
boneMatrices,
boneTexture,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Skeleton';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(bones)) {
bones = [];
}
this.bones = bones;
/**
* An array of Matrix4s that represent the inverse of the matrixWorld of the individual bones.
*/
if (GameLib.Utils.UndefinedOrNull(boneInverses)) {
boneInverses = [];
}
this.boneInverses = boneInverses;
/**
* Use a vertex texture in the shader - allows for more than 4 bones per vertex, not supported by all devices
*/
if (GameLib.Utils.UndefinedOrNull(useVertexTexture)) {
useVertexTexture = false;
}
this.useVertexTexture = useVertexTexture;
if (useVertexTexture) {
console.warn('support for vertex texture bones is not supported yet - something could break somewhere');
}
if (GameLib.Utils.UndefinedOrNull(boneTextureWidth)) {
boneTextureWidth = 0;
}
this.boneTextureWidth = boneTextureWidth;
if (GameLib.Utils.UndefinedOrNull(boneTextureHeight)) {
boneTextureHeight = 0;
}
this.boneTextureHeight = boneTextureHeight;
if (GameLib.Utils.UndefinedOrNull(boneMatrices)) {
boneMatrices = [];
}
this.boneMatrices = boneMatrices;
if (GameLib.Utils.UndefinedOrNull(boneTexture)) {
boneTexture = null;
}
this.boneTexture = boneTexture;
};
GameLib.D3.API.Skeleton.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Skeleton.prototype.constructor = GameLib.D3.API.Skeleton;
/**
* Creates an API skeleton from an Object skeleton
* @param objectSkeleton
* @constructor
*/
GameLib.D3.API.Skeleton.FromObject = function(objectSkeleton) {
return new GameLib.D3.API.Skeleton(
objectSkeleton.id,
objectSkeleton.name,
objectSkeleton.bones.map(
function (objectBone) {
return GameLib.D3.API.Bone.FromObject(objectBone);
}
),
objectSkeleton.boneInverses.map(
function (boneInverse) {
return GameLib.D3.API.Matrix4.FromObject(boneInverse);
}
),
objectSkeleton.useVertexTexture,
objectSkeleton.boneTextureWidth,
objectSkeleton.boneTextureHeight,
objectSkeleton.boneMatrices.map(
function (boneMatrix) {
return GameLib.D3.API.Matrix4.FromObject(boneMatrix);
}
),
objectSkeleton.boneTexture,
objectSkeleton.parentEntity
);
};
/**
* Raw Solver API object - should always correspond with the Solver Schema
* @param id
* @param name
* @param solverType
* @param iterations
* @param tolerance
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Solver = function(
id,
name,
solverType,
iterations,
tolerance,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Solver (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(solverType)) {
solverType = GameLib.D3.Solver.GS_SOLVER;
}
this.solverType = solverType;
if (GameLib.Utils.UndefinedOrNull(iterations)) {
iterations = 10;
}
this.iterations = iterations;
if (GameLib.Utils.UndefinedOrNull(tolerance)) {
tolerance = 1e-7;
}
this.tolerance = tolerance;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Solver.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Solver.prototype.constructor = GameLib.D3.API.Solver;
/**
* Creates an API Solver from an Object Solver
* @param objectSolver
* @constructor
*/
GameLib.D3.API.Solver.FromObject = function(objectSolver) {
return new GameLib.D3.API.Solver(
objectSolver.id,
objectSolver.name,
objectSolver.solverType,
objectSolver.iterations,
objectSolver.tolerance,
objectSolver.parentEntity
);
};
/**
* API Spline
* @param id String
* @param name String
* @param vertices GameLib.API.Vector3[]
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Spline = function(
id,
name,
vertices,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Spline (unknown)';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(vertices)) {
vertices = [];
}
this.vertices = vertices;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Spline.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Spline.prototype.constructor = GameLib.D3.API.Spline;
/**
* Object to GameLib.D3.API.Spline
* @param objectComponent
* @constructor
*/
GameLib.D3.API.Spline.FromObject = function(objectComponent) {
return new GameLib.D3.API.Spline(
objectComponent.id,
objectComponent.name,
objectComponent.vertices.map(
function (objectVertex) {
return GameLib.API.Vector3.FromObject(objectVertex);
}
),
objectComponent.parentEntity
);
};
/**
* Raw Texture API object - should always correspond with the Texture Schema
* @param id
* @param typeId
* @param name
* @param image
* @param images
* @param wrapS
* @param wrapT
* @param repeat
* @param data
* @param format
* @param mapping
* @param magFilter
* @param minFilter
* @param textureType
* @param anisotropy
* @param offset
* @param generateMipmaps
* @param flipY
* @param mipmaps
* @param unpackAlignment
* @param premultiplyAlpha
* @param encoding
* @param canvas
* @param animated
* @param reverseAnimation
* @param forward
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Texture = function(
id,
typeId,
name,
image,
images,
wrapS,
wrapT,
repeat,
data,
format,
mapping,
magFilter,
minFilter,
textureType,
anisotropy,
offset,
generateMipmaps,
flipY,
mipmaps,
unpackAlignment,
premultiplyAlpha,
encoding,
canvas,
animated,
reverseAnimation,
forward,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(typeId)) {
typeId = GameLib.D3.Texture.TEXTURE_TYPE_NORMAL;
}
this.typeId = typeId;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Texture (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(image)) {
image = null;
}
this.image = image;
if (GameLib.Utils.UndefinedOrNull(images)) {
images = [];
}
this.images = images;
if (GameLib.Utils.UndefinedOrNull(wrapS)) {
wrapS = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING;
}
this.wrapS = wrapS;
if (GameLib.Utils.UndefinedOrNull(wrapT)) {
wrapT = GameLib.D3.Texture.TYPE_REPEAT_WRAPPING;
}
this.wrapT = wrapT;
if (GameLib.Utils.UndefinedOrNull(repeat)) {
repeat = new GameLib.API.Vector2(1, 1);
}
this.repeat = repeat;
if (GameLib.Utils.UndefinedOrNull(data)) {
data = null;
}
this.data = data;
if (GameLib.Utils.UndefinedOrNull(format)) {
format = GameLib.D3.Texture.TYPE_RGBA_FORMAT;
}
this.format = format;
if (GameLib.Utils.UndefinedOrNull(mapping)) {
mapping = GameLib.D3.Texture.TYPE_UV_MAPPING;
}
this.mapping = mapping;
if (GameLib.Utils.UndefinedOrNull(magFilter)) {
magFilter = GameLib.D3.Texture.TYPE_LINEAR_FILTER;
}
this.magFilter = magFilter;
if (GameLib.Utils.UndefinedOrNull(minFilter)) {
minFilter = GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER;
}
this.minFilter = minFilter;
if (GameLib.Utils.UndefinedOrNull(textureType)) {
textureType = GameLib.D3.Texture.TYPE_UNSIGNED_BYTE;
}
this.textureType = textureType;
if (GameLib.Utils.UndefinedOrNull(anisotropy)) {
anisotropy = 1;
}
this.anisotropy = anisotropy;
if (GameLib.Utils.UndefinedOrNull(offset)) {
offset = new GameLib.API.Vector2(0, 0);
}
this.offset = offset;
if (GameLib.Utils.UndefinedOrNull(generateMipmaps)) {
generateMipmaps = true;
}
this.generateMipmaps = generateMipmaps;
if (GameLib.Utils.UndefinedOrNull(flipY)) {
flipY = true;
}
this.flipY = flipY;
if (GameLib.Utils.UndefinedOrNull(mipmaps)) {
mipmaps = [];
}
this.mipmaps = mipmaps;
if (GameLib.Utils.UndefinedOrNull(unpackAlignment)) {
unpackAlignment = 4;
}
this.unpackAlignment = unpackAlignment;
if (GameLib.Utils.UndefinedOrNull(premultiplyAlpha)) {
premultiplyAlpha = false;
}
this.premultiplyAlpha = premultiplyAlpha;
if (GameLib.Utils.UndefinedOrNull(encoding)) {
encoding = GameLib.D3.Texture.TYPE_LINEAR_ENCODING;
}
this.encoding = encoding;
if (GameLib.Utils.UndefinedOrNull(canvas)) {
canvas = null;
}
this.canvas = canvas;
if (GameLib.Utils.UndefinedOrNull(animated)) {
animated = false;
}
this.animated = animated;
if (GameLib.Utils.UndefinedOrNull(reverseAnimation)) {
reverseAnimation = false;
}
this.reverseAnimation = reverseAnimation;
if (GameLib.Utils.UndefinedOrNull(forward)) {
forward = true;
}
this.forward = forward;
this.needsUpdate = false;
};
GameLib.D3.API.Texture.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Texture.prototype.constructor = GameLib.D3.API.Texture;
/**
* Creates an API texture from Object data
* @param objectTexture
* @constructor
*/
GameLib.D3.API.Texture.FromObject = function(objectTexture) {
return new GameLib.D3.API.Texture(
objectTexture.id,
objectTexture.typeId,
objectTexture.name,
objectTexture.image,
objectTexture.images,
objectTexture.wrapS,
objectTexture.wrapT,
GameLib.API.Vector2.FromObject(objectTexture.repeat),
objectTexture.data,
objectTexture.format,
objectTexture.mapping,
objectTexture.magFilter,
objectTexture.minFilter,
objectTexture.textureType,
objectTexture.anisotropy,
GameLib.API.Vector2.FromObject(objectTexture.offset),
objectTexture.generateMipmaps,
objectTexture.flipY,
objectTexture.mipmaps,
objectTexture.unpackAlignment,
objectTexture.premultiplyAlpha,
objectTexture.encoding,
objectTexture.canvas,
objectTexture.animated,
objectTexture.reverseAnimation,
objectTexture.forward,
objectTexture.parentEntity
)
};
/**
* API Vertex
* @param position GameLib.API.Vector3
* @param boneWeights GameLib.API.BoneWeight[]
* @constructor
*/
GameLib.D3.API.Vertex = function(
position,
boneWeights
) {
if (GameLib.Utils.UndefinedOrNull(position)) {
position = new GameLib.API.Vector3();
}
this.position = position;
if (GameLib.Utils.UndefinedOrNull(boneWeights)) {
boneWeights = [];
}
this.boneWeights = boneWeights;
};
/**
* Creates an API vertex from an Object vertex
* @param objectVertex
* @constructor
*/
GameLib.D3.API.Vertex.FromObject = function(objectVertex) {
return new GameLib.D3.API.Vertex(
GameLib.API.Vector3.FromObject(objectVertex.position),
objectVertex.boneWeights.map(
function(boneWeight) {
return GameLib.D3.API.BoneWeight.FromObject(boneWeight);
}
)
);
};
/**
* Raw Viewport API object - should always correspond with the Viewport Schema
* @param id
* @param name
* @param width
* @param height
* @param x
* @param y
* @param parentEntity
* @constructor
*/
GameLib.D3.API.Viewport = function(
id,
name,
width,
height,
x,
y,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Viewport (' + this.id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(width)) {
width = 800;
}
this.width = width;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 600;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(x)) {
x = 0;
}
this.x = x;
if (GameLib.Utils.UndefinedOrNull(y)) {
y = 0;
}
this.y = y;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
};
GameLib.D3.API.Viewport.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.API.Viewport.prototype.constructor = GameLib.D3.API.Viewport;
/**
* Creates an API Viewport from an Object Viewport
* @param objectViewport
* @constructor
*/
GameLib.D3.API.Viewport.FromObject = function(objectViewport) {
return new GameLib.D3.API.Viewport(
objectViewport.id,
objectViewport.name,
objectViewport.width,
objectViewport.height,
objectViewport.x,
objectViewport.y,
objectViewport.parentEntity
);
};
/**
* Creates a Animation object
* @param apiAnimation GameLib.D3.API.Animation
* @constructor
*/
GameLib.D3.Animation = function(
apiAnimation
) {
if (GameLib.Utils.UndefinedOrNull(apiAnimation)) {
apiAnimation = {};
}
if (apiAnimation instanceof GameLib.D3.Animation) {
return apiAnimation;
}
GameLib.D3.API.Animation.call(
this,
apiAnimation.id,
apiAnimation.name,
apiAnimation.rotationSpeed,
apiAnimation.translationSpeed,
apiAnimation.scaleSpeed,
apiAnimation.rotationFn,
apiAnimation.translationFn,
apiAnimation.scaleFn,
apiAnimation.blocking,
apiAnimation.applyToMeshWhenDone,
apiAnimation.meshes,
apiAnimation.parentEntity
);
this.functionType = GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_ROTATION;
this.editor = null;
/**
* This indicates whether an animation is currently in process - for blocking to take effect
* @type {boolean}
*/
this.inProcess = false;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_ANIMATION,
{
'meshes' : [GameLib.D3.Mesh]
}
);
};
GameLib.D3.Animation.prototype = Object.create(GameLib.D3.API.Animation.prototype);
GameLib.D3.Animation.prototype.constructor = GameLib.D3.Animation;
GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_ROTATION = 1;
GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_TRANSLATION = 2;
GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_SCALE = 3;
GameLib.D3.Animation.prototype.createInstance = function() {
this.instance = {
rotation : null,
translation : null,
scale : null
};
try {
if (this.rotationFn) {
this.instance.rotation = new Function(
'data',
this.rotationFn
).bind(this);
}
if (this.translationFn) {
this.instance.translation = new Function(
'data',
this.translationFn
).bind(this);
}
if (this.scaleFn) {
this.instance.scale = new Function(
'data',
this.scaleFn
).bind(this);
}
} catch (error) {
console.error(error);
this.publish(
GameLib.Event.ANIMATION_COMPILE_FAILED,
{
component : this
}
)
}
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Animation.prototype.updateInstance = function() {
try {
if (this.rotationFn) {
this.instance.rotation = new Function('data', this.rotationFn).bind(this);
this.publish(
GameLib.Event.ANIMATION_COMPILE_SUCCESS,
{
component : this,
type : GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_ROTATION
}
)
}
if (this.translationFn) {
this.instance.translation = new Function('data', this.translationFn).bind(this);
this.publish(
GameLib.Event.ANIMATION_COMPILE_SUCCESS,
{
component : this,
type : GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_TRANSLATION
}
)
}
if (this.scaleFn) {
this.instance.scale = new Function('data', this.scaleFn).bind(this);
this.publish(
GameLib.Event.ANIMATION_COMPILE_SUCCESS,
{
component : this,
type : GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_SCALE
}
)
}
} catch (error) {
console.error(error);
this.publish(
GameLib.Event.ANIMATION_COMPILE_FAILED,
{
component : this
}
)
}
};
/**
* Converts a GameLib.D3.Animation to a new GameLib.D3.API.Animation
* @returns {GameLib.D3.API.Animation}
*/
GameLib.D3.Animation.prototype.toApiObject = function() {
return new GameLib.D3.API.Animation(
this.id,
this.name,
this.rotationSpeed,
this.translationSpeed,
this.scaleSpeed,
this.rotationFn,
this.translationFn,
this.scaleFn,
this.blocking,
this.applyToMeshWhenDone,
this.meshes.map(
function(mesh) {
return GameLib.Utils.IdOrNull(mesh);
}
),
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts from an Object Animation to a GameLib.D3.Animation
* @param objectAnimation Object
* @returns {GameLib.D3.Animation}
* @constructor
*/
GameLib.D3.Animation.FromObject = function(objectAnimation) {
var apiAnimation = GameLib.D3.API.Animation.FromObject(objectAnimation);
return new GameLib.D3.Animation(
apiAnimation
);
};
GameLib.D3.Animation.prototype.launchEditor = function(){
GameLib.Event.Emit(
GameLib.Event.GET_CODER_IMPLEMENTATION,
null,
function(coder) {
this.coder = coder;
this.coder.isNotCodeMirrorThrow();
}.bind(this)
);
var property = null;
if (this.functionType === GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_ROTATION) {
this.rotationFn = '//when the animation is complete, return true\nreturn true;';
property = 'rotationFn';
}
if (this.functionType === GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_TRANSLATION) {
this.translationFn = '//when the animation is complete, return true\nreturn true;';
property = 'translationFn';
}
if (this.functionType === GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_SCALE) {
this.scaleFn = '//when the animation is complete, return true\nreturn true;';
property = 'scaleFn';
}
if (property) {
this.editor = this.coder.instance(
document.body,
{
value : this[property],
mode : 'javascript',
lineNumbers : true,
scrollbarStyle : 'overlay'
}
);
this.editor.on('change', function(){
this[property] = this.editor.getValue();
this.updateInstance();
}.bind(this))
} else {
console.warn('invalid function type selected');
}
};
GameLib.D3.Animation.prototype.closeEditor = function(){
var dom = this.editor.getWrapperElement();
dom.parentElement.removeChild(dom);
};
GameLib.D3.Animation.prototype.addMesh = function(mesh) {
GameLib.Utils.PushUnique(this.meshes, mesh);
GameLib.Event.Emit(
GameLib.Event.ANIMATION_MESH_ADDED,
{
animation : this,
mesh : mesh
}
)
};
GameLib.D3.Animation.prototype.removeMesh = function(mesh) {
var index = this.meshes.indexOf(mesh);
this.meshes.splice(index, 1);
GameLib.Event.Emit(
GameLib.Event.ANIMATION_MESH_REMOVED,
{
animation : this,
mesh : mesh
}
)
};
/**
* Creates a Audio object
* @param graphics GameLib.D3.Graphics
* @param apiAudio GameLib.D3.API.Audio
* @constructor
*/
GameLib.D3.Audio = function(
graphics,
apiAudio
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiAudio)) {
apiAudio = {};
}
if (apiAudio instanceof GameLib.D3.Audio) {
return apiAudio;
}
GameLib.D3.API.Audio.call(
this,
apiAudio.id,
apiAudio.name,
apiAudio.path,
apiAudio.loop,
apiAudio.volume,
apiAudio.camera,
apiAudio.overplay,
apiAudio.pause,
apiAudio.parentEntity
);
if (this.camera instanceof GameLib.D3.API.Camera) {
this.camera = new GameLib.D3.Camera(
this.graphics,
this.camera
)
}
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_AUDIO,
{
'camera' : GameLib.D3.Camera
}
);
};
GameLib.D3.Audio.prototype = Object.create(GameLib.D3.API.Audio.prototype);
GameLib.D3.Audio.prototype.constructor = GameLib.D3.Audio;
/**
* Audio create instance
*/
GameLib.D3.Audio.prototype.createInstance = function() {
if (GameLib.Utils.UndefinedOrNull(this.camera) ||
GameLib.Utils.UndefinedOrNull(this.camera.instance)) {
console.log('audio not ready to create instance');
return;
}
GameLib.Event.Emit(
GameLib.Event.GET_API_URL,
null,
function(data) {
this.apiUrl = data.apiUrl;
}.bind(this)
);
//Create an AudioListener and add it to the camera
var listener = new THREE.AudioListener();
this.camera.instance.add( listener );
// create a global audio source
this.instance = new THREE.Audio( listener );
var audioLoader = new THREE.AudioLoader();
//Load a sound and set it as the Audio object's buffer
audioLoader.load(
this.apiUrl + this.path + '?ts=' + Date.now(),
function( buffer ) {
this.instance.setBuffer( buffer );
this.instance.setLoop( this.loop );
this.instance.setVolume( this.volume );
GameLib.Component.prototype.createInstance.call(this);
}.bind(this)
);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Audio.prototype.updateInstance = function(property) {
if (property === 'loop') {
this.instance.setLoop(this.loop);
}
if (property === 'volume') {
this.instance.setVolume(this.volume);
}
if (property === 'paused') {
if (this.paused) {
this.instance.pause();
} else {
this.instance.play();
}
}
};
/**
* Converts a GameLib.D3.Audio to a new GameLib.D3.API.Audio
* @returns {GameLib.D3.API.Audio}
*/
GameLib.D3.Audio.prototype.toApiObject = function() {
return new GameLib.D3.API.Audio(
this.id,
this.name,
this.path,
this.loop,
this.volume,
GameLib.Utils.IdOrNull(this.camera),
this.overplay,
this.paused,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts from an Object Audio to a GameLib.D3.Audio
* @param graphics GameLib.D3.Graphics
* @param objectAudio Object
* @returns {GameLib.D3.Audio}
* @constructor
*/
GameLib.D3.Audio.FromObject = function(graphics, objectAudio) {
var apiAudio = GameLib.D3.API.Audio.FromObject(objectAudio);
return new GameLib.D3.Audio(
graphics,
apiAudio
);
};
GameLib.D3.Audio.prototype.play = function() {
this.instance.play();
};
/**
* BoneWeight Superset
* @constructor
* @param graphics GameLib.D3.Graphics
* @param apiBoneWeight GameLib.D3.API.BoneWeight
*/
GameLib.D3.BoneWeight = function (
graphics,
apiBoneWeight
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiBoneWeight)) {
apiBoneWeight = {};
}
if (apiBoneWeight instanceof GameLib.D3.BoneWeight) {
return apiBoneWeight;
}
GameLib.D3.API.BoneWeight.call(
this,
apiBoneWeight.boneIndex,
apiBoneWeight.weight
);
};
GameLib.D3.BoneWeight.prototype = Object.create(GameLib.D3.API.BoneWeight.prototype);
GameLib.D3.BoneWeight.prototype.constructor = GameLib.D3.BoneWeight;
/**
* Converts a GameLib.D3.BoneWeight to GameLib.D3.API.BoneWeight
* @returns {GameLib.D3.API.BoneWeight}
*/
GameLib.D3.BoneWeight.prototype.toApiObject = function() {
var apiBoneWeight = new GameLib.D3.API.BoneWeight(
this.boneIndex,
this.weight
);
return apiBoneWeight;
};
/**
* Returns a GameLib.D3.BoneWeight from a boneWeight Object
* @param graphics GameLib.D3.Graphics
* @param objectBoneWeight Object
* @returns {GameLib.D3.BoneWeight}
* @constructor
*/
GameLib.D3.BoneWeight.FromObject = function(
graphics,
objectBoneWeight
) {
var apiBoneWeight = GameLib.D3.API.BoneWeight.FromObject(objectBoneWeight);
var boneWeight = new GameLib.D3.BoneWeight(
graphics,
apiBoneWeight
);
return boneWeight;
};
/**
* Bone Superset
* @constructor
* @param graphics GameLib.D3.Graphics
* @param apiBone GameLib.D3.API.Bone
*/
GameLib.D3.Bone = function (
graphics,
apiBone
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiBone)) {
apiBone = {};
}
if (apiBone instanceof GameLib.D3.Bone) {
return apiBone;
}
GameLib.D3.API.Bone.call(
this,
apiBone.id,
apiBone.name,
apiBone.childBoneIds,
apiBone.parentBoneIds,
apiBone.position,
apiBone.quaternion,
apiBone.scale,
apiBone.up
);
this.position = new GameLib.Vector3(
graphics,
this.position,
this
);
this.quaternion = new GameLib.Quaternion(
graphics,
this.quaternion,
this
);
this.scale = new GameLib.Vector3(
graphics,
this.scale,
this
);
this.up = new GameLib.Vector3(
graphics,
this.up,
this
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_BONE
);
};
GameLib.D3.Bone.prototype = Object.create(GameLib.D3.API.Bone.prototype);
GameLib.D3.Bone.prototype.constructor = GameLib.D3.Bone;
/**
* Creates an instance bone
*/
GameLib.D3.Bone.prototype.createInstance = function() {
this.instance = new THREE.Bone();
this.instance.name = this.name;
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
this.instance.quaternion.x = this.quaternion.x;
this.instance.quaternion.y = this.quaternion.y;
this.instance.quaternion.z = this.quaternion.z;
this.instance.quaternion.w = this.quaternion.w;
this.instance.scale.x = this.scale.x;
this.instance.scale.y = this.scale.y;
this.instance.scale.z = this.scale.z;
this.instance.up.x = this.up.x;
this.instance.up.y = this.up.y;
this.instance.up.z = this.up.z;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance
*/
GameLib.D3.Bone.prototype.updateInstance = function() {
this.instance.name = this.name;
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
this.instance.quaternion.x = this.quaternion.x;
this.instance.quaternion.y = this.quaternion.y;
this.instance.quaternion.z = this.quaternion.z;
this.instance.quaternion.w = this.quaternion.w;
this.instance.scale.x = this.scale.x;
this.instance.scale.y = this.scale.y;
this.instance.scale.z = this.scale.z;
this.instance.up.x = this.up.x;
this.instance.up.y = this.up.y;
this.instance.up.z = this.up.z;
};
/**
* Converts a GameLib.D3.Bone to GameLib.D3.API.Bone
* @returns {GameLib.D3.API.Bone}
*/
GameLib.D3.Bone.prototype.toApiObject = function() {
var apiBone = new GameLib.D3.API.Bone(
this.id,
this.name,
this.childBoneIds,
this.parentBoneIds,
this.position.toApiObject(),
this.quaternion.toApiObject(),
this.scale.toApiObject(),
this.up.toApiObject()
);
return apiBone;
};
/**
* Returns a GameLib.D3.Bone from a bone Object
* @param graphics GameLib.D3.Graphics
* @param objectBone Object
* @returns {GameLib.D3.Bone}
* @constructor
*/
GameLib.D3.Bone.FromObject = function(
graphics,
objectBone
) {
var apiBone = GameLib.D3.API.Bone.FromObject(objectBone);
var bone = GameLib.D3.Bone(
graphics,
apiBone
);
return bone;
};
/**
* Broadphase Runtime
* @param physics GameLib.D3.Graphics
* @param apiBroadphase GameLib.D3.API.Broadphase
* @constructor
*/
GameLib.D3.Broadphase = function (
physics,
apiBroadphase
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiBroadphase)) {
apiBroadphase = {};
}
if (apiBroadphase instanceof GameLib.D3.Broadphase) {
return apiBroadphase;
}
GameLib.D3.API.Broadphase.call(
this,
apiBroadphase.id,
apiBroadphase.name,
apiBroadphase.broadphaseType,
apiBroadphase.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_BROADPHASE
);
};
GameLib.D3.Broadphase.prototype = Object.create(GameLib.D3.API.Broadphase.prototype);
GameLib.D3.Broadphase.prototype.constructor = GameLib.D3.Broadphase;
/**
*
* @returns {*}
*/
GameLib.D3.Broadphase.prototype.createInstance = function() {
if (this.broadphaseType === GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE) {
this.instance = new CANNON.NaiveBroadphase();
} else if (this.broadphaseType === GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID) {
this.instance = new CANNON.GridBroadphase();
} else if (this.broadphaseType === GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP) {
this.instance = new CANNON.SAPBroadphase();
} else {
console.warn('Unsupported broadphase type: ' + this.broadphaseType);
throw new Error('Unsupported broadphase type: ' + this.broadphaseType);
}
GameLib.Component.prototype.createInstance.call(this);
};
/**
*
*/
GameLib.D3.Broadphase.prototype.updateInstance = function() {
if (this.broadphaseType === GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE) {
if (!(this.instance instanceof CANNON.NaiveBroadphase)) {
this.createInstance();
}
}
if (this.broadphaseType === GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID) {
if (!(this.instance instanceof CANNON.GridBroadphase)) {
this.createInstance();
}
}
if (this.broadphaseType === GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP) {
if (!(this.instance instanceof CANNON.SAPBroadphase)) {
this.createInstance();
}
}
};
/**
* GameLib.D3.Broadphase to GameLib.D3.API.Broadphase
* @returns {GameLib.D3.API.Broadphase}
*/
GameLib.D3.Broadphase.prototype.toApiObject = function() {
var apiBroadphase = new GameLib.D3.API.Broadphase(
this.id,
this.name,
this.broadphaseType,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiBroadphase;
};
/**
* GameLib.D3.Broadphase from Object Broadphase
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.Broadphase}
* @constructor
*/
GameLib.D3.Broadphase.FromObject = function(graphics, objectComponent) {
var apiBroadphase = GameLib.D3.API.Broadphase.FromObject(objectComponent);
return new GameLib.D3.Broadphase(
graphics,
apiBroadphase
);
};
/**
* Broadphase Types
* @type {number}
*/
GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE = 0x1;
GameLib.D3.Broadphase.BROADPHASE_TYPE_GRID = 0x2;
GameLib.D3.Broadphase.BROADPHASE_TYPE_SAP = 0x3;
/**
* Creates a Camera object
* @param graphics GameLib.D3.Graphics
* @param apiCamera GameLib.D3.API.Camera
* @constructor
*/
GameLib.D3.Camera = function(
graphics,
apiCamera
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiCamera)) {
apiCamera = {};
}
if (apiCamera instanceof GameLib.D3.Camera) {
return apiCamera;
}
GameLib.D3.API.Camera.call(
this,
apiCamera.id,
apiCamera.cameraType,
apiCamera.name,
apiCamera.fov,
apiCamera.aspect,
apiCamera.near,
apiCamera.far,
apiCamera.position,
apiCamera.lookAt,
apiCamera.minX,
apiCamera.maxX,
apiCamera.minY,
apiCamera.maxY,
apiCamera.minZ,
apiCamera.maxZ,
apiCamera.offsetX,
apiCamera.offsetY,
apiCamera.quaternion,
apiCamera.parentEntity,
apiCamera.eyeSeparation,
apiCamera.focalLength
);
if (this.position instanceof GameLib.API.Vector3) {
this.position = new GameLib.Vector3(
graphics,
this.position,
this
);
} else {
console.warn('position not instance of API.Vector3');
throw new Error('position not instance of API.Vector3');
}
if (this.quaternion instanceof GameLib.API.Quaternion) {
this.quaternion = new GameLib.Quaternion(
graphics,
this.quaternion,
this
);
} else {
console.warn('quaternion not instance of API.Quaternion');
throw new Error('quaternion not instance of API.Quaternion');
}
if (this.lookAt instanceof GameLib.API.Vector3) {
this.lookAt = new GameLib.Vector3(
graphics,
this.lookAt,
this
);
} else {
console.warn('lookAt not instance of API.Vector3');
throw new Error('lookAt not instance of API.Vector3');
}
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_CAMERA
);
} ;
GameLib.D3.Camera.prototype = Object.create(GameLib.D3.API.Camera.prototype);
GameLib.D3.Camera.prototype.constructor = GameLib.D3.Camera;
GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE = 0x1;
GameLib.D3.Camera.CAMERA_TYPE_ORTHOGONAL = 0x2;
GameLib.D3.Camera.CAMERA_TYPE_STEREO = 0x3;
/**
* Creates a camera instance of 'graphics' type (only THREE for now)
* @returns {THREE.Camera}
*/
GameLib.D3.Camera.prototype.createInstance = function() {
if (this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE ) {
this.instance = new THREE.PerspectiveCamera(
this.fov,
this.aspect,
this.near,
this.far
);
} else if (this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_ORTHOGONAL) {
this.instance = new THREE.OrthographicCamera(
this.minX + this.offsetX,
this.maxX + this.offsetX,
this.maxY,
this.minY,
this.minZ,
this.maxZ
);
} else if (this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_STEREO) {
this.instance = new THREE.StereoCamera();
} else {
throw new Error('unsupported camera type : ' + this.cameraType);
}
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
this.instance.quaternion.x = this.quaternion.x;
this.instance.quaternion.y = this.quaternion.y;
this.instance.quaternion.z = this.quaternion.z;
this.instance.quaternion.w = this.quaternion.w;
this.instance.lookAt(this.lookAt.instance);
this.instance.updateProjectionMatrix();
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Camera.prototype.updateInstance = function(property) {
if (GameLib.Utils.UndefinedOrNull(property)) {
console.warn('no camera property specified for : ' + this.name);
}
if (property === 'cameraType') {
if (
this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_ORTHOGONAL &&
!(this.instance instanceof THREE.OrthographicCamera)
) {
this.createInstance();
}
if (
this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE &&
!(this.instance instanceof THREE.PerspectiveCamera)
) {
this.createInstance();
}
}
if (
property === 'aspect' ||
property === 'minX' ||
property === 'maxX' ||
property === 'minY' ||
property === 'maxY' ||
property === 'minZ' ||
property === 'maxZ' ||
property === 'offsetX' ||
property === 'offsetY' ||
property === 'fov' ||
property === 'near' ||
property === 'far' ||
property === 'eyeSeparation' ||
property === 'focalLength'
) {
if (this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_ORTHOGONAL) {
this.minX = this.aspect * this.minY;
this.maxX = this.aspect * this.maxY;
this.instance.left = this.minX + this.offsetX;
this.instance.right = this.maxX + this.offsetX;
this.instance.bottom = this.minY + this.offsetY;
this.instance.top = this.maxY + this.offsetY;
this.instance.near = this.minZ;
this.instance.far = this.maxZ;
}
if (
this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE ||
this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_STEREO
) {
this.instance.fov = this.fov;
this.instance.aspect = this.aspect;
this.instance.near = this.near;
this.instance.far = this.far;
}
if (this.cameraType === GameLib.D3.Camera.CAMERA_TYPE_STEREO) {
this.instance.eyeSeparation = this.eyeSeparation;
this.instance.focalLength = this.focalLength;
this.instance.update(this.instance);
}
}
if (property === 'position') {
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
}
if (property === 'quaternion') {
this.instance.quaternion.x = this.quaternion.x;
this.instance.quaternion.y = this.quaternion.y;
this.instance.quaternion.z = this.quaternion.z;
this.instance.quaternion.w = this.quaternion.w;
}
if (property === 'lookAt') {
this.lookAt.instance.x = this.lookAt.x;
this.lookAt.instance.y = this.lookAt.y;
this.lookAt.instance.z = this.lookAt.z;
this.instance.lookAt(this.lookAt.instance);
}
this.instance.updateProjectionMatrix();
};
/**
* Resize default
* @param width
* @param height
*/
GameLib.D3.Camera.prototype.resize = function(width, height) {
camera.aspect = width / height;
camera.updateInstance();
};
/**
* Converts a GameLib.D3.Camera to a new GameLib.D3.API.Camera
* @returns {GameLib.D3.API.Camera}
*/
GameLib.D3.Camera.prototype.toApiObject = function() {
return new GameLib.D3.API.Camera(
this.id,
this.cameraType,
this.name,
this.fov,
this.aspect,
this.near,
this.far,
this.position.toApiObject(),
this.lookAt.toApiObject(),
this.minX,
this.maxX,
this.minY,
this.maxY,
this.minZ,
this.maxZ,
this.offsetX,
this.offsetY,
this.quaternion.toApiObject(),
GameLib.Utils.IdOrNull(this.parentEntity),
this.eyeSeparation,
this.focalLength
);
};
/**
* Converts from an Object Camera to a GameLib.D3.Camera
* @param graphics GameLib.D3.Graphics
* @param objectCamera Object
* @returns {GameLib.D3.Camera}
* @constructor
*/
GameLib.D3.Camera.FromObject = function(graphics, objectCamera) {
var apiCamera = GameLib.D3.API.Camera.FromObject(objectCamera);
return new GameLib.D3.Camera(
graphics,
apiCamera
);
};
/**
* 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() {
this.instance = document.createElement('canvas');
this.instance.width = this.width;
this.instance.height = this.height;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Canvas.prototype.updateInstance = function() {
if (GameLib.Utils.UndefinedOrNull(this.instance)) {
this.createInstance();
}
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)
);
};
/**
* Coder
* @param id
* @param name
* @param coderType
* @constructor
*/
GameLib.D3.Coder = function Coder(
id,
name,
coderType
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Coder (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(coderType)) {
coderType = GameLib.D3.Coder.CODER_TYPE_CODE_MIRROR;
}
this.coderType = coderType;
this.createInstance();
};
/**
* GameLib.D3.Coder Types
* @type {number}
*/
GameLib.D3.Coder.CODER_TYPE_CODE_MIRROR = 0x1;
/**
* @returns {THREE.Coder}
*/
GameLib.D3.Coder.prototype.createInstance = function() {
this.instance = CodeMirror;
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Coder.prototype.updateInstance = function() {
};
/**
* True if THREE physics
* @returns {boolean}
*/
GameLib.D3.Coder.prototype.isCodeMirror = function() {
return (this.coderType === GameLib.D3.Coder.CODER_TYPE_CODE_MIRROR)
};
/**
* Logs a warning and throws an error if not cannon
*/
GameLib.D3.Coder.prototype.isNotCodeMirrorThrow = function() {
if (this.coderType !== GameLib.D3.Coder.CODER_TYPE_CODE_MIRROR) {
console.warn('Only CodeMirror supported for this function');
throw new Error('Only CodeMirror supported for this function');
}
};
/**
* Renders a scene with a camera
* @param graphics GameLib.D3.Graphics
* @param apiComposer GameLib.D3.API.Composer
* @constructor
*/
GameLib.D3.Composer = function (
graphics,
apiComposer
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiComposer)) {
apiComposer = {};
}
if (apiComposer instanceof GameLib.D3.Composer) {
return apiComposer;
}
GameLib.D3.API.Composer.call(
this,
apiComposer.id,
apiComposer.name,
apiComposer.renderer,
apiComposer.renderTarget,
apiComposer.passes,
apiComposer.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_COMPOSER,
{
'renderer' : GameLib.D3.Renderer,
'renderTarget' : GameLib.D3.RenderTarget,
'passes' : [GameLib.D3.Pass]
}
);
};
GameLib.D3.Composer.prototype = Object.create(GameLib.D3.API.Composer.prototype);
GameLib.D3.Composer.prototype.constructor = GameLib.D3.Composer;
/**
* Creates a Composer instance
* @returns {*}
*/
GameLib.D3.Composer.prototype.createInstance = function() {
//TODO : Fix this too - make it nice (no circular references)
// var instance = null;
//
// if (update) {
// instance = this.instance;
// }
//TODO : Fix this still (renderer and renderTarget should be objects)
// if (this.renderer &&
// this.renderTarget) {
//
// if (!THREE.EffectComposer) {
// console.warn('No THREE.EffectComposer');
// throw new Error('No THREE.EffectComposer');
// }
//
// instance = new THREE.EffectComposer(
// this.renderer.instance,
// this.renderTarget.instance
// );
//
// this.passes.map(
// function(pass) {
// this.instance.addPass(pass.instance);
// }.bind(this)
// );
// }
console.log('GameLib.D3.Composer.prototype.createInstance() - fix me');
GameLib.Component.prototype.createInstance.call(this);
//return instance;
};
/**
* Updates Composer instance
*/
GameLib.D3.Composer.prototype.updateInstance = function() {
console.log('GameLib.D3.Composer.prototype.updateInstance() - fix me');
};
/**
* GameLib.D3.Composer to GameLib.D3.API.Composer
* @returns {GameLib.D3.API.Composer}
*/
GameLib.D3.Composer.prototype.toApiObject = function() {
var apiComposer = new GameLib.D3.API.Composer(
this.id,
this.name,
GameLib.Utils.IdOrNull(this.renderer),
GameLib.Utils.IdOrNull(this.renderTarget),
this.passes.map(
function(pass) {
return GameLib.Utils.IdOrNull(pass);
}
),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiComposer;
};
/**
*
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.Composer}
* @constructor
*/
GameLib.D3.Composer.FromObject = function(graphics, objectComponent) {
var apiComposer = GameLib.D3.API.Composer.FromObject(objectComponent);
return new GameLib.D3.Composer(
graphics,
apiComposer
);
};
/**
* Controls Superset - The apiControls properties get moved into the Controls object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiControls GameLib.D3.API.Controls
* @constructor
*/
GameLib.D3.Controls = function (
graphics,
apiControls
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiControls)) {
apiControls = {};
}
if (apiControls instanceof GameLib.D3.Controls) {
return apiControls;
}
GameLib.D3.API.Controls.call(
this,
apiControls.id,
apiControls.controlsType,
apiControls.name,
apiControls.domElement,
apiControls.parentEntity
);
var componentType = GameLib.Component.COMPONENT_CONTROLS;
var linkedObjects = {
domElement : GameLib.DomElement
};
var delayed = false;
if (this.controlsType === GameLib.D3.Controls.CONTROLS_TYPE_EDITOR) {
componentType = GameLib.Component.COMPONENT_CONTROLS_EDITOR;
linkedObjects.raycaster = GameLib.D3.Raycaster;
linkedObjects.camera = GameLib.D3.Camera;
delayed = true;
}
if (this.controlsType === GameLib.D3.Controls.CONTROLS_TYPE_TOUCH) {
componentType = GameLib.Component.COMPONENT_CONTROLS_TOUCH
}
if (this.controlsType === GameLib.D3.Controls.CONTROLS_TYPE_KEYBOARD) {
componentType = GameLib.Component.COMPONENT_CONTROLS_KEYBOARD
}
if (this.controlsType === GameLib.D3.Controls.CONTROLS_TYPE_MOUSE) {
componentType = GameLib.Component.COMPONENT_CONTROLS_MOUSE
}
GameLib.Component.call(
this,
componentType,
linkedObjects,
delayed
);
};
GameLib.D3.Controls.prototype = Object.create(GameLib.D3.API.Controls.prototype);
GameLib.D3.Controls.prototype.constructor = GameLib.D3.Controls;
/**
* Controls Type
* @type {number}
*/
GameLib.D3.Controls.CONTROLS_TYPE_EDITOR = 0x0;
GameLib.D3.Controls.CONTROLS_TYPE_TOUCH = 0x1;
GameLib.D3.Controls.CONTROLS_TYPE_KEYBOARD = 0x2;
GameLib.D3.Controls.CONTROLS_TYPE_MOUSE = 0x3;
/**
* Creates a mesh instance or updates it
*/
GameLib.D3.Controls.prototype.createInstance = function() {
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the mesh instance
*/
GameLib.D3.Controls.prototype.updateInstance = function() {
console.log('default controls update instance');
};
/**
* Converts a GameLib.D3.Controls to a GameLib.D3.API.Controls
* @returns {GameLib.D3.API.Controls}
*/
GameLib.D3.Controls.prototype.toApiObject = function() {
var apiControls = new GameLib.D3.API.Controls(
this.id,
this.controlsType,
this.name,
GameLib.Utils.IdOrNull(this.domElement),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiControls;
};
/**
* Converts a data object to a GameLib.D3.Controls
* @param graphics GameLib.D3.Graphics
* @param objectControls {Object}
* @constructor
*/
GameLib.D3.Controls.FromObject = function(graphics, objectControls) {
var apiControls = GameLib.D3.API.Controls.FromObject(objectControls);
return new GameLib.D3.Controls(
graphics,
apiControls
);
};
/**
* Controls Superset - The apiControls properties get moved into the Controls object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiControls GameLib.D3.API.Controls
* @param raycaster
* @param camera
* @constructor
*/
GameLib.D3.Controls.Editor = function (
graphics,
apiControls,
raycaster,
camera
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(raycaster)) {
raycaster = null;
}
this.raycaster = raycaster;
if (GameLib.Utils.UndefinedOrNull(camera)) {
camera = null;
}
this.camera = camera;
if (this.raycaster instanceof GameLib.D3.API.Raycaster) {
this.raycaster = new GameLib.D3.Raycaster(
this.graphics,
this.raycaster
);
}
if (this.camera instanceof GameLib.D3.API.Camera) {
this.camera = new GameLib.D3.Camera(
this.graphics,
this.camera
)
}
GameLib.D3.Controls.call(
this,
this.graphics,
apiControls
);
};
/**
* Inheritance
* @type {GameLib.D3.Controls}
*/
GameLib.D3.Controls.Editor.prototype = Object.create(GameLib.D3.Controls.prototype);
GameLib.D3.Controls.Editor.prototype.constructor = GameLib.D3.Controls.Editor;
/**
* Create Instance
* @returns {THREE.EditorControls}
*/
GameLib.D3.Controls.Editor.prototype.createInstance = function() {
if (!this.camera || !this.camera.instance) {
throw new Error('No camera at time of instance');
}
if (!this.domElement || !this.domElement.instance) {
throw new Error('No dom element at time of instance');
}
this.instance = new THREE.EditorControls(
this.camera.instance,
this.domElement.instance
);
GameLib.D3.Controls.prototype.createInstance.call(this);
};
/**
* Update Instance
*/
GameLib.D3.Controls.Editor.prototype.updateInstance = function() {
console.warn('an update instance was called on editor controls - which, if not called from within a running system at the right time will affect the order of input event handling and cause system instability');
GameLib.D3.Controls.prototype.updateInstance.call(this);
};
/**
* Converts a GameLib.D3.Controls.Editor to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Controls}
*/
GameLib.D3.Controls.Editor.prototype.toApiObject = function() {
var apiControls = GameLib.D3.Controls.prototype.toApiObject.call(this);
apiControls.raycaster = GameLib.Utils.IdOrNull(this.raycaster);
apiControls.camera = GameLib.Utils.IdOrNull(this.camera);
return apiControls;
};
/**
* Construct an Editor Controls object from data
* @param graphics
* @param objectControls
* @returns {GameLib.D3.Controls.Editor}
* @constructor
*/
GameLib.D3.Controls.Editor.FromObject = function(graphics, objectControls) {
var apiControls = GameLib.D3.API.Controls.FromObject(objectControls);
return new GameLib.D3.Controls.Editor(
graphics,
apiControls,
objectControls.raycaster,
objectControls.camera
);
};
/**
* Keyboard Controls
* @param graphics GameLib.D3.Graphics
* @param apiControls GameLib.D3.API.Controls
* @constructor
*/
GameLib.D3.Controls.Keyboard = function (
graphics,
apiControls
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
GameLib.D3.Controls.call(
this,
this.graphics,
apiControls
);
};
/**
* Inheritance
* @type {GameLib.D3.Controls}
*/
GameLib.D3.Controls.Keyboard.prototype = Object.create(GameLib.D3.Controls.prototype);
GameLib.D3.Controls.Keyboard.prototype.constructor = GameLib.D3.Controls.Keyboard;
/**
* Create Instance
* @returns
*/
GameLib.D3.Controls.Keyboard.prototype.createInstance = function() {
/**
* Set instance to true to indicate no dependencies to other components
*/
this.instance = true;
GameLib.D3.Controls.prototype.createInstance.call(this);
};
/**
* Update Instance
*/
GameLib.D3.Controls.Keyboard.prototype.updateInstance = function() {
GameLib.D3.Controls.prototype.updateInstance.call(this);
};
/**
* Converts a GameLib.D3.Controls.Keyboard to a GameLib.D3.API.Controls
* @returns {GameLib.D3.API.Controls}
*/
GameLib.D3.Controls.Keyboard.prototype.toApiObject = function() {
var apiControls = GameLib.D3.Controls.prototype.toApiObject.call(this);
/**
* add other properties here as this component develops...
*/
return apiControls;
};
/**
* Construct an Keyboard Controls object from data
* @param graphics
* @param objectControls
* @returns {GameLib.D3.Controls.Keyboard}
* @constructor
*/
GameLib.D3.Controls.Keyboard.FromObject = function(graphics, objectControls) {
var apiControls = GameLib.D3.API.Controls.FromObject(objectControls);
return new GameLib.D3.Controls.Keyboard(
graphics,
apiControls
);
};
/**
* Mouse Controls
* @param graphics GameLib.D3.Graphics
* @param apiControls GameLib.D3.API.Controls
* @constructor
*/
GameLib.D3.Controls.Mouse = function (
graphics,
apiControls
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
GameLib.D3.Controls.call(
this,
this.graphics,
apiControls
);
};
/**
* Inheritance
* @type {GameLib.D3.Controls}
*/
GameLib.D3.Controls.Mouse.prototype = Object.create(GameLib.D3.Controls.prototype);
GameLib.D3.Controls.Mouse.prototype.constructor = GameLib.D3.Controls.Mouse;
/**
* Create Instance
* @returns
*/
GameLib.D3.Controls.Mouse.prototype.createInstance = function() {
/**
* Set instance to true to indicate no dependencies to other components
*/
this.instance = true;
GameLib.D3.Controls.prototype.createInstance.call(this);
};
/**
* Update Instance
*/
GameLib.D3.Controls.Mouse.prototype.updateInstance = function() {
GameLib.D3.Controls.prototype.updateInstance.call(this);
};
/**
* Converts a GameLib.D3.Controls.Mouse to a GameLib.D3.API.Controls
* @returns {GameLib.D3.API.Controls}
*/
GameLib.D3.Controls.Mouse.prototype.toApiObject = function() {
var apiControls = GameLib.D3.Controls.prototype.toApiObject.call(this);
/**
* add other properties here as this component develops...
*/
return apiControls;
};
/**
* Construct an Mouse Controls object from data
* @param graphics
* @param objectControls
* @returns {GameLib.D3.Controls.Mouse}
* @constructor
*/
GameLib.D3.Controls.Mouse.FromObject = function(graphics, objectControls) {
var apiControls = GameLib.D3.API.Controls.FromObject(objectControls);
return new GameLib.D3.Controls.Mouse(
graphics,
apiControls
);
};
/**
* Touch Controls
* @param graphics GameLib.D3.Graphics
* @param apiControls GameLib.D3.API.Controls
* @param sensitivity
* @constructor
*/
GameLib.D3.Controls.Touch = function (
graphics,
apiControls,
sensitivity
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(sensitivity)) {
sensitivity = 5;
}
this.sensitivity = sensitivity;
GameLib.D3.Controls.call(
this,
this.graphics,
apiControls
);
};
/**
* Inheritance
* @type {GameLib.D3.Controls}
*/
GameLib.D3.Controls.Touch.prototype = Object.create(GameLib.D3.Controls.prototype);
GameLib.D3.Controls.Touch.prototype.constructor = GameLib.D3.Controls.Touch;
/**
* Create Instance
* @returns
*/
GameLib.D3.Controls.Touch.prototype.createInstance = function() {
/**
* Set instance to true to indicate no dependencies to other components
*/
this.instance = true;
GameLib.D3.Controls.prototype.createInstance.call(this);
};
/**
* Update Instance
*/
GameLib.D3.Controls.Touch.prototype.updateInstance = function() {
GameLib.D3.Controls.prototype.updateInstance.call(this);
};
/**
* Converts a GameLib.D3.Controls.Touch to a GameLib.D3.API.Controls
* @returns {GameLib.D3.API.Controls}
*/
GameLib.D3.Controls.Touch.prototype.toApiObject = function() {
var apiControls = GameLib.D3.Controls.prototype.toApiObject.call(this);
apiControls.sensitivity = this.sensitivity;
/**
* add other properties here as this component develops...
*/
return apiControls;
};
/**
* Construct an Touch Controls object from data
* @param graphics
* @param objectControls
* @returns {GameLib.D3.Controls.Touch}
* @constructor
*/
GameLib.D3.Controls.Touch.FromObject = function(graphics, objectControls) {
var apiControls = GameLib.D3.API.Controls.FromObject(objectControls);
return new GameLib.D3.Controls.Touch(
graphics,
apiControls,
objectControls.sensitivity
);
};
/**
* Creates a CustomCode object
* @param apiCustomCode GameLib.D3.API.CustomCode
* @constructor
*/
GameLib.D3.CustomCode = function(
apiCustomCode
) {
if (GameLib.Utils.UndefinedOrNull(apiCustomCode)) {
apiCustomCode = {};
}
if (apiCustomCode instanceof GameLib.D3.CustomCode) {
return apiCustomCode;
}
GameLib.D3.API.CustomCode.call(
this,
apiCustomCode.id,
apiCustomCode.name,
apiCustomCode.eventId,
apiCustomCode.code,
apiCustomCode.parentEntity
);
this.editor = null;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_CUSTOM_CODE
);
};
GameLib.D3.CustomCode.prototype = Object.create(GameLib.D3.API.CustomCode.prototype);
GameLib.D3.CustomCode.prototype.constructor = GameLib.D3.CustomCode;
GameLib.D3.CustomCode.prototype.createInstance = function() {
try {
this.instance = new Function('data', this.code).bind(this);
} catch (error) {
/**
* Set the instance to true here to indicate that even though the compilation failed, the instance will be fine and
* this component loaded fine.
*/
this.instance = new Function('data', "console.log('compilation failed for : " + this.name + "');").bind(this);
}
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.CustomCode.prototype.updateInstance = function() {
try {
this.instance = new Function('data', this.code).bind(this);
this.publish(
GameLib.Event.COMPILE_SUCCESS,
{
component : this
}
)
} catch (error) {
this.instance = new Function('data', "console.log('compilation update failed for : " + this.name + "');").bind(this);
this.publish(
GameLib.Event.COMPILE_FAILED,
{
component : this
}
)
}
};
/**
* Converts a GameLib.D3.CustomCode to a new GameLib.D3.API.CustomCode
* @returns {GameLib.D3.API.CustomCode}
*/
GameLib.D3.CustomCode.prototype.toApiObject = function() {
return new GameLib.D3.API.CustomCode(
this.id,
this.name,
this.eventId,
this.code,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts from an Object CustomCode to a GameLib.D3.CustomCode
* @param objectCustomCode Object
* @returns {GameLib.D3.CustomCode}
* @constructor
*/
GameLib.D3.CustomCode.FromObject = function(objectCustomCode) {
var apiCustomCode = GameLib.D3.API.CustomCode.FromObject(objectCustomCode);
return new GameLib.D3.CustomCode(
apiCustomCode
);
};
GameLib.D3.CustomCode.prototype.launchEditor = function(){
GameLib.Event.Emit(
GameLib.Event.GET_CODER_IMPLEMENTATION,
null,
function(coder) {
this.coder = coder;
this.coder.isNotCodeMirrorThrow();
}.bind(this)
);
this.editor = this.coder.instance(
document.body,
{
value : this.code,
mode : 'javascript',
lineNumbers : true,
scrollbarStyle : 'overlay',
indentWithTabs: true,
indentUnit : 4
}
);
this.editor.on('change', function(){
this.code = this.editor.getValue();
this.updateInstance();
}.bind(this))
};
GameLib.D3.CustomCode.prototype.closeEditor = function(){
var dom = this.editor.getWrapperElement();
dom.parentElement.removeChild(dom);
};
/**
* Face
* @constructor
* @param implementation
* @param apiFace
*/
GameLib.D3.Face = function Face(
implementation,
apiFace
) {
this.implementation = implementation;
if (implementation instanceof GameLib.D3.Graphics) {
this.implementation.isNotThreeThrow();
} else if (implementation instanceof GameLib.D3.Physics) {
this.implementation.isNotCannonThrow();
} else {
throw new Error('Unhandled implementation : ' + implementation);
}
if (GameLib.Utils.UndefinedOrNull(apiFace)) {
apiFace = {};
}
if (apiFace instanceof GameLib.D3.Face) {
return apiFace;
}
GameLib.D3.API.Face.call(
this,
apiFace.id,
apiFace.name,
apiFace.v0index,
apiFace.v1index,
apiFace.v2index,
apiFace.materialIndex,
apiFace.uvs,
apiFace.color,
apiFace.vertexColors,
apiFace.vertexNormals,
apiFace.normal
);
if (this.implementation instanceof GameLib.D3.Graphics) {
/**
* physics faces have no color... a little sad right?
*/
this.color = new GameLib.Color(
this.implementation,
this.color,
this
);
this.vertexColors = this.vertexColors.map(function(vertexColor){
if (vertexColor instanceof GameLib.Color) {
return vertexColor;
}
if (vertexColor instanceof GameLib.API.Color) {
return new GameLib.Color(
this.implementation,
vertexColor,
this
)
}
console.warn('unknown vertex color type', vertexColor);
}.bind(this));
}
this.vertexNormals = this.vertexNormals.map(function(vertexNormal){
if (vertexNormal instanceof GameLib.Vector3) {
return vertexNormal;
}
if (vertexNormal instanceof GameLib.API.Vector3) {
return new GameLib.Vector3(
this.implementation,
vertexNormal,
this
)
}
console.warn('unknown vertex normal type', vertexNormal);
}.bind(this));
this.uvs = this.uvs.reduce(
function(result, uvArray, index) {
result[index] = uvArray.reduce(
function(uvResult, uv) {
if (uv instanceof GameLib.API.Vector2) {
uvResult.push(
new GameLib.Vector2(
this.implementation,
uv,
this
)
);
} else {
console.warn('unknown uv type');
}
return uvResult;
}.bind(this),
[]
);
return result;
}.bind(this),
[]
);
this.normal = new GameLib.Vector3(
this.implementation,
this.normal,
this
);
};
GameLib.D3.Face.prototype = Object.create(GameLib.D3.API.Face.prototype);
GameLib.D3.Face.prototype.constructor = GameLib.D3.Face;
GameLib.D3.Face.prototype.createInstance = function() {
};
GameLib.D3.Face.prototype.updateInstance = function() {
};
GameLib.D3.Face.prototype.toApiObject = function() {
return new GameLib.D3.API.Face(
this.id,
this.name,
this.v0index,
this.v1index,
this.v2index,
this.materialIndex,
this.uvs.reduce(
function(result, uvArray, index) {
result[index] = uvArray.reduce(
function(uvResult, uv) {
if (uv instanceof GameLib.Vector2) {
uvResult.push(uv.toApiObject());
} else {
console.warn('unknown uv type - cannot commit to API');
}
return uvResult;
}.bind(this),
[]
);
return result;
}.bind(this),
[]
),
this.color.toApiObject(),
this.vertexColors.map(function(vertexColor){
return vertexColor.toApiObject();
}),
this.vertexNormals.map(function(vertexNormal){
return vertexNormal.toApiObject();
}),
this.normal.toApiObject()
);
};
/**
* @param implementation
* @param objectFace
* @returns {GameLib.D3.Face}
* @constructor
*/
GameLib.D3.Face.FromObject = function(implementation, objectFace) {
return new GameLib.D3.Face(
implementation,
GameLib.D3.API.Face.FromObject(objectFace)
);
};
/**
* Fog Superset - The apiFog properties get moved into the Fog object itself, and then the instance is
* created
* @param graphics
* @param apiFog GameLib.D3.API.Fog
* @constructor
*/
GameLib.D3.Fog = function (
graphics,
apiFog
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiFog)) {
apiFog = {};
}
if (apiFog instanceof GameLib.D3.Fog) {
return apiFog;
}
GameLib.D3.API.Fog.call(
this,
apiFog.id,
apiFog.name,
apiFog.exponential,
apiFog.color,
apiFog.near,
apiFog.far,
apiFog.density,
apiFog.parentEntity
);
this.color = new GameLib.Color(
this.graphics,
this.color,
this
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_FOG
);
};
GameLib.D3.Fog.prototype = Object.create(GameLib.D3.API.Fog.prototype);
GameLib.D3.Fog.prototype.constructor = GameLib.D3.Fog;
/**
* Creates an instance scene
* @returns {THREE.Fog}
*/
GameLib.D3.Fog.prototype.createInstance = function() {
if (this.exponential) {
this.instance = new THREE.FogExp2(
this.color.instance,
this.density
);
} else {
this.instance = new THREE.Fog(
this.color.instance,
this.near,
this.far
);
}
this.instance.name = this.name;
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.Fog.prototype.updateInstance = function(property) {
if (property === 'exponential') {
if (
this.exponential &&
!(this.instance instanceof THREE.FogExp2)
) {
this.createInstance();
return;
}
if (
!this.exponential &&
!(this.instance instanceof THREE.Fog)
) {
this.createInstance();
return;
}
}
if (property === 'color') {
this.color.instance.setRGB(
this.color.r,
this.color.g,
this.color.b
);
this.instance.color = this.color.instance;
}
if (property === 'near' || property === 'far') {
if (this.instance instanceof THREE.Fog) {
this.instance.near = this.near;
this.instance.far = this.far;
}
}
if (property === 'density') {
if (this.instance instanceof THREE.FogExp2) {
this.instance.density = this.density;
}
}
};
/**
* Converts a GameLib.D3.Fog to a GameLib.D3.API.Fog
* @returns {GameLib.D3.API.Fog}
*/
GameLib.D3.Fog.prototype.toApiObject = function() {
return new GameLib.D3.API.Fog(
this.id,
this.name,
this.exponential,
this.color.toApiObject(),
this.near,
this.far,
this.density,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts a scene Object to a GameLib.D3.Fog object
* @param graphics GameLib.D3.Graphics
* @param objectFog Object
* @returns {GameLib.D3.Fog}
* @constructor
*/
GameLib.D3.Fog.FromObject = function(
graphics,
objectFog
) {
var apiFog = GameLib.D3.API.Fog.FromObject(objectFog);
return new GameLib.D3.Fog(
graphics,
apiFog
);
};
/**
* Font Superset - The apiFont properties get moved into the Font object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiFont GameLib.D3.API.Font
* @constructor
*/
GameLib.D3.Font = function(
graphics,
apiFont
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiFont)) {
apiFont = {};
}
if (apiFont instanceof GameLib.D3.Font) {
return apiFont;
}
GameLib.D3.API.Font.call(
this,
apiFont.id,
apiFont.name,
apiFont.url,
apiFont.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_FONT
);
};
GameLib.D3.Font.prototype = Object.create(GameLib.D3.API.Font.prototype);
GameLib.D3.Font.prototype.constructor = GameLib.D3.Font;
/**
* Creates a light instance
* @returns {*}
*/
GameLib.D3.Font.prototype.createInstance = function() {
GameLib.Event.Emit(
GameLib.Event.LOAD_FONT,
{
font : this
},
function(fontInstance) {
this.instance = fontInstance;
GameLib.Component.prototype.createInstance.call(this);
}.bind(this),
function(error) {
console.error(error);
this.instance = null;
GameLib.Component.prototype.createInstance.call(this);
}.bind(this)
);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Font.prototype.updateInstance = function() {
GameLib.Event.Emit(
GameLib.Event.LOAD_FONT,
{
font : this
}
);
};
/**
* Converts a GameLib.D3.Font to a GameLib.D3.API.Font
* @returns {GameLib.D3.API.Font}
*/
GameLib.D3.Font.prototype.toApiObject = function() {
return new GameLib.D3.API.Font(
this.id,
this.name,
this.url,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Returns a new GameLib.D3.Font from a GameLib.D3.API.Font
* @param graphics GameLib.D3.Graphics
* @param objectFont GameLib.D3.API.Font
* @returns {GameLib.D3.Font}
*/
GameLib.D3.Font.FromObject = function(graphics, objectFont) {
return new GameLib.D3.Font(
graphics,
GameLib.D3.API.Font.FromObject(objectFont)
);
};
/**
* FrictionContactMaterial Runtime
* @param physics GameLib.D3.Graphics
* @param apiFrictionContactMaterial GameLib.D3.API.FrictionContactMaterial
* @constructor
*/
GameLib.D3.FrictionContactMaterial = function (
physics,
apiFrictionContactMaterial
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiFrictionContactMaterial)) {
apiFrictionContactMaterial = {};
}
if (apiFrictionContactMaterial instanceof GameLib.D3.FrictionContactMaterial) {
return apiFrictionContactMaterial;
}
GameLib.D3.API.FrictionContactMaterial.call(
this,
apiFrictionContactMaterial.id,
apiFrictionContactMaterial.name,
apiFrictionContactMaterial.materials,
apiFrictionContactMaterial.friction,
apiFrictionContactMaterial.restitution,
apiFrictionContactMaterial.contactEquationStiffness,
apiFrictionContactMaterial.contactEquationRelaxation,
apiFrictionContactMaterial.frictionEquationStiffness,
apiFrictionContactMaterial.frictionEquationRelaxation,
apiFrictionContactMaterial.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_FRICTION_CONTACT_MATERIAL,
{
materials : [GameLib.D3.FrictionMaterial]
}
);
};
GameLib.D3.FrictionContactMaterial.prototype = Object.create(GameLib.D3.API.FrictionContactMaterial.prototype);
GameLib.D3.FrictionContactMaterial.prototype.constructor = GameLib.D3.FrictionContactMaterial;
/**
*
* @returns {*}
*/
GameLib.D3.FrictionContactMaterial.prototype.createInstance = function() {
this.instance = new CANNON.ContactMaterial(
null,
null,
{
friction: this.friction,
restitution: this.restitution,
contactEquationStiffness: this.contactEquationStiffness
}
);
this.instance.materials = this.materials.map(
function(material){
return material.instance;
}
);
GameLib.Component.prototype.createInstance.call(this);
};
/**
*
*/
GameLib.D3.FrictionContactMaterial.prototype.updateInstance = function() {
this.instance.materials = this.materials.map(
function(material) {
return material.instance;
}
);
this.instance.friction = this.friction;
this.instance.restitution = this.restitution;
this.instance.contactEquationStiffness = this.contactEquationStiffness;
this.instance.contactEquationRelaxation = this.contactEquationRelaxation;
this.instance.frictionEquationStiffness = this.frictionEquationStiffness;
this.instance.frictionEquationRelaxation = this.frictionEquationRelaxation;
};
/**
* GameLib.D3.FrictionContactMaterial to GameLib.D3.API.FrictionContactMaterial
* @returns {GameLib.D3.API.FrictionContactMaterial}
*/
GameLib.D3.FrictionContactMaterial.prototype.toApiObject = function() {
var apiFrictionContactMaterial = new GameLib.D3.API.FrictionContactMaterial(
this.id,
this.name,
this.materials.map(
function(material) {
return GameLib.Utils.IdOrNull(material);
}
),
this.friction,
this.restitution,
this.contactEquationStiffness,
this.contactEquationRelaxation,
this.frictionEquationStiffness,
this.frictionEquationRelaxation,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiFrictionContactMaterial;
};
/**
* GameLib.D3.FrictionContactMaterial from Object FrictionContactMaterial
* @param physics
* @param objectComponent
* @returns {GameLib.D3.FrictionContactMaterial}
* @constructor
*/
GameLib.D3.FrictionContactMaterial.FromObject = function(physics, objectComponent) {
var apiFrictionContactMaterial = GameLib.D3.API.FrictionContactMaterial.FromObject(objectComponent);
return new GameLib.D3.FrictionContactMaterial(
physics,
apiFrictionContactMaterial
);
};
/**
* FrictionMaterial Runtime
* @param physics GameLib.D3.Graphics
* @param apiFrictionMaterial GameLib.D3.API.FrictionMaterial
* @constructor
*/
GameLib.D3.FrictionMaterial = function (
physics,
apiFrictionMaterial
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiFrictionMaterial)) {
apiFrictionMaterial = {};
}
if (apiFrictionMaterial instanceof GameLib.D3.FrictionMaterial) {
return apiFrictionMaterial;
}
GameLib.D3.API.FrictionMaterial.call(
this,
apiFrictionMaterial.id,
apiFrictionMaterial.name,
apiFrictionMaterial.friction,
apiFrictionMaterial.restitution,
apiFrictionMaterial.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_FRICTION_MATERIAL
);
};
GameLib.D3.FrictionMaterial.prototype = Object.create(GameLib.D3.API.FrictionMaterial.prototype);
GameLib.D3.FrictionMaterial.prototype.constructor = GameLib.D3.FrictionMaterial;
/**
* create instance
*/
GameLib.D3.FrictionMaterial.prototype.createInstance = function() {
this.instance = new CANNON.Material(
this.name
);
this.instance.friction = this.friction;
this.instance.restitution = this.restitution;
GameLib.Component.prototype.createInstance.call(this);
};
/**
*
*/
GameLib.D3.FrictionMaterial.prototype.updateInstance = function() {
this.instance.friction = this.friction;
this.instance.restitution = this.restitution;
this.instance.name = this.name;
};
/**
* GameLib.D3.FrictionMaterial to GameLib.D3.API.FrictionMaterial
* @returns {GameLib.D3.API.FrictionMaterial}
*/
GameLib.D3.FrictionMaterial.prototype.toApiObject = function() {
var apiFrictionMaterial = new GameLib.D3.API.FrictionMaterial(
this.id,
this.name,
this.friction,
this.restitution,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiFrictionMaterial;
};
/**
* GameLib.D3.FrictionMaterial from Object FrictionMaterial
* @param physics
* @param objectComponent
* @returns {GameLib.D3.FrictionMaterial}
* @constructor
*/
GameLib.D3.FrictionMaterial.FromObject = function(physics, objectComponent) {
var apiFrictionMaterial = GameLib.D3.API.FrictionMaterial.FromObject(objectComponent);
return new GameLib.D3.FrictionMaterial(
physics,
apiFrictionMaterial
);
};
/**
* Graphics
* @param id
* @param name
* @param graphicsType
* @constructor
*/
GameLib.D3.Graphics = function Graphics(
id,
name,
graphicsType
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Graphics (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(graphicsType)) {
graphicsType = GameLib.D3.Graphics.GRAPHICS_TYPE_THREE;
}
this.graphicsType = graphicsType;
this.createInstance();
};
/**
* GameLib.D3.Graphics Types
* @type {number}
*/
GameLib.D3.Graphics.GRAPHICS_TYPE_THREE = 0x1;
/**
* @returns {THREE.Graphics}
*/
GameLib.D3.Graphics.prototype.createInstance = function() {
this.instance = THREE;
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Graphics.prototype.updateInstance = function() {
};
/**
* True if THREE physics
* @returns {boolean}
*/
GameLib.D3.Graphics.prototype.isThree = function() {
return (this.graphicsType === GameLib.D3.Graphics.GRAPHICS_TYPE_THREE)
};
/**
* Logs a warning and throws an error if not cannon
*/
GameLib.D3.Graphics.prototype.isNotThreeThrow = function() {
if (this.graphicsType !== GameLib.D3.Graphics.GRAPHICS_TYPE_THREE) {
console.warn('Only THREE supported for this function');
throw new Error('Only THREE supported for this function');
}
};
/**
* Helpers for displaying outlines or making 'invisible' scene objects visible
* @param graphics GameLib.D3.Graphics
* @param id
* @param name
* @param object
* @param helperType
* @param parentEntity
* @constructor
*/
GameLib.D3.Helper = function(
graphics,
id,
name,
object,
helperType,
parentEntity
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Helper (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(object)) {
console.warn('Cannot create a helper for an Object which does not exist');
throw new Error('Cannot create a helper for an Object which does not exist');
}
this.object = object;
if (GameLib.Utils.UndefinedOrNull(helperType)) {
helperType = GameLib.D3.Helper.HELPER_TYPE_NONE;
if (
object instanceof GameLib.D3.Mesh &&
object.meshType !== GameLib.D3.Mesh.MESH_TYPE_CURVE
) {
helperType = GameLib.D3.Helper.HELPER_TYPE_EDGES;
}
if (object instanceof GameLib.D3.Light) {
if (object.lightType === GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL) {
helperType = GameLib.D3.Helper.HELPER_TYPE_DIRECTIONAL_LIGHT;
}
if (object.lightType === GameLib.D3.Light.LIGHT_TYPE_POINT) {
helperType = GameLib.D3.Helper.HELPER_TYPE_POINT_LIGHT;
}
if (object.lightType === GameLib.D3.Light.LIGHT_TYPE_SPOT) {
helperType = GameLib.D3.Helper.HELPER_TYPE_SPOT_LIGHT;
}
}
if (object instanceof GameLib.D3.Skeleton) {
helperType = GameLib.D3.Helper.HELPER_TYPE_SKELETON;
}
}
this.helperType = helperType;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
this.createInstance();
/**
* A helper as a component - does this make sense at all?
*/
// GameLib.Component.call(
// this,
// GameLib.Component.COMPONENT_HELPER
// );
};
GameLib.D3.Helper.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.Helper.prototype.constructor = GameLib.D3.Helper;
/**
* Helper types
* @type {string}
*/
GameLib.D3.Helper.HELPER_TYPE_NONE = 0x0;
GameLib.D3.Helper.HELPER_TYPE_EDGES = 0x1;
GameLib.D3.Helper.HELPER_TYPE_DIRECTIONAL_LIGHT = 0x2;
GameLib.D3.Helper.HELPER_TYPE_SPOT_LIGHT = 0x3;
GameLib.D3.Helper.HELPER_TYPE_POINT_LIGHT = 0x4;
GameLib.D3.Helper.HELPER_TYPE_WIREFRAME = 0x5;
GameLib.D3.Helper.HELPER_TYPE_SKELETON = 0x6;
/**
* Creates a helper instance
*/
GameLib.D3.Helper.prototype.createInstance = function() {
if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_EDGES) {
this.instance = new THREE.LineSegments(
new THREE.EdgesGeometry(
this.object.instance.geometry
),
new THREE.LineBasicMaterial(
{
color:0x00ff00,
linewidth:2
}
)
)
}
if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_DIRECTIONAL_LIGHT) {
this.instance = new THREE.DirectionalLightHelper(this.object.instance);
}
if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_POINT_LIGHT) {
this.instance = new THREE.PointLightHelper(this.object.instance, 1);
}
if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_SPOT_LIGHT) {
this.instance = new THREE.SpotLightHelper(this.object.instance);
}
if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_WIREFRAME) {
this.instance = new THREE.WireframeGeometry(this.object.instance, 0x00FF00);
}
if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_SKELETON) {
this.instance = new THREE.SkeletonHelper(this.object.instance);
}
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Helper.prototype.updateInstance = function() {
this.instance.position.copy(this.object.instance.position);
if (this.object.instance.parentMesh && this.object.instance.parentMesh.instance) {
this.instance.position.add(this.object.instance.parentMesh.instance.position);
}
this.instance.scale.copy(this.object.instance.scale);
this.instance.quaternion.copy(this.object.instance.quaternion);
};
/**
* Image
* @constructor
* @param graphics
* @param apiImage
*/
GameLib.D3.Image = function(
graphics,
apiImage
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiImage)) {
apiImage = {};
}
if (apiImage instanceof GameLib.D3.Image) {
return apiImage;
}
GameLib.D3.API.Image.call(
this,
apiImage.id,
apiImage.name,
apiImage.fileName,
apiImage.extension,
apiImage.path,
apiImage.contentType,
apiImage.size,
apiImage.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_IMAGE,
null,
true
);
GameLib.Event.Emit(
GameLib.Event.LOAD_IMAGE,
{
image : this
}
);
};
GameLib.D3.Image.prototype = Object.create(GameLib.D3.API.Image.prototype);
GameLib.D3.Image.prototype.constructor = GameLib.D3.Image;
/**
* Creates an image instance
* @returns {*}
*/
GameLib.D3.Image.prototype.createInstance = function() {
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Image.prototype.updateInstance = function() {
this.createInstance();
};
/**
*
* @returns {GameLib.D3.API.Image}
*/
GameLib.D3.Image.prototype.toApiObject = function() {
var apiImage = new GameLib.D3.API.Image(
this.id,
this.name,
this.fileName,
this.extension,
this.path,
this.contentType,
this.size,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiImage;
};
/**
* @param graphics
* @param objectImage
* @returns {GameLib.D3.Image}
* @constructor
*/
GameLib.D3.Image.FromObject = function(graphics, objectImage) {
return new GameLib.D3.Image(
graphics,
GameLib.D3.API.Image.FromObject(objectImage)
);
};
/**
* Light Superset - The apiLight properties get moved into the Light object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiLight GameLib.D3.API.Light
* @constructor
*/
GameLib.D3.Light = function(
graphics,
apiLight
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiLight)) {
apiLight = {};
}
if (apiLight instanceof GameLib.D3.Light) {
return apiLight;
}
GameLib.D3.API.Light.call(
this,
apiLight.id,
apiLight.lightType,
apiLight.name,
apiLight.color,
apiLight.intensity,
apiLight.position,
apiLight.targetPosition,
apiLight.quaternion,
apiLight.rotation,
apiLight.scale,
apiLight.distance,
apiLight.decay,
apiLight.power,
apiLight.angle,
apiLight.penumbra,
apiLight.parentScene,
apiLight.parentEntity
);
this.color = new GameLib.Color(
graphics,
this.color,
this
);
this.position = new GameLib.Vector3(
graphics,
this.position,
this
);
this.targetPosition = new GameLib.Vector3(
graphics,
this.targetPosition,
this
);
this.scale = new GameLib.Vector3(
graphics,
this.scale,
this
);
this.quaternion = new GameLib.Quaternion(
graphics,
this.quaternion,
this
);
this.rotation = new GameLib.Vector3(
graphics,
this.rotation,
this
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_LIGHT,
{
'parentScene' : GameLib.D3.Scene
}
);
};
GameLib.D3.Light.prototype = Object.create(GameLib.D3.API.Light.prototype);
GameLib.D3.Light.prototype.constructor = GameLib.D3.Light;
/**
* Light Types
* @type {number}
*/
GameLib.D3.Light.LIGHT_TYPE_AMBIENT = 0x1;
GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL = 0x2;
GameLib.D3.Light.LIGHT_TYPE_POINT = 0x3;
GameLib.D3.Light.LIGHT_TYPE_SPOT = 0x4;
/**
* Creates a light instance
* @returns {*}
*/
GameLib.D3.Light.prototype.createInstance = function() {
if (
this.lightType === GameLib.D3.Light.LIGHT_TYPE_AMBIENT ||
this.lightType === 'AmbientLight'
) {
this.instance = new THREE.AmbientLight(
this.color.instance,
this.intensity
);
} else if (
this.lightType === GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL ||
this.lightType === 'DirectionalLight'
) {
this.instance = new THREE.DirectionalLight(
this.color.instance,
this.intensity
);
} else if (
this.lightType === GameLib.D3.Light.LIGHT_TYPE_POINT ||
this.lightType === 'PointLight'
) {
this.instance = new THREE.PointLight(
this.color.instance,
this.intensity
);
this.instance.distance = this.distance;
this.instance.decay = this.decay;
} else if (
this.lightType === GameLib.D3.Light.LIGHT_TYPE_SPOT ||
this.lightType === 'SpotLight'
) {
this.instance = new THREE.SpotLight(
this.color.instance,
this.intensity
);
this.instance.distance = this.distance;
this.instance.angle = this.angle;
this.instance.penumbra = this.penumbra;
this.instance.decay = this.decay;
} else {
console.warn('unsupported light type: ' + this.lightType);
return;
}
this.instance.name = this.name;
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
this.instance.scale.x = this.scale.x;
this.instance.scale.y = this.scale.y;
this.instance.scale.z = this.scale.z;
if (this.instance.target) {
this.instance.target.position.x = this.targetPosition.x;
this.instance.target.position.y = this.targetPosition.y;
this.instance.target.position.z = this.targetPosition.z;
}
this.instance.quaternion.x = this.quaternion.x;
this.instance.quaternion.y = this.quaternion.y;
this.instance.quaternion.z = this.quaternion.z;
this.instance.quaternion.w = this.quaternion.w;
this.instance.intensity = this.intensity;
this.instance.color.set(this.color.toHex());
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Light.prototype.updateInstance = function(property) {
if (GameLib.Utils.UndefinedOrNull(property)) {
console.warn('no property for light: ' + this.name);
}
if (property === 'lightType') {
this.parentScene.instance.remove(this.instance);
this.createInstance();
this.parentScene.instance.add(this.instance);
}
if (property === 'name') {
this.instance.name = this.name;
}
if (property === 'position') {
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
}
if (property === 'scale') {
this.instance.scale.x = this.scale.x;
this.instance.scale.y = this.scale.y;
this.instance.scale.z = this.scale.z;
}
if (property === 'target') {
if (this.instance.target) {
this.instance.target.position.x = this.targetPosition.x;
this.instance.target.position.y = this.targetPosition.y;
this.instance.target.position.z = this.targetPosition.z;
}
}
if (property === 'quaternion') {
this.instance.quaternion.x = this.quaternion.x;
this.instance.quaternion.y = this.quaternion.y;
this.instance.quaternion.z = this.quaternion.z;
this.instance.quaternion.w = this.quaternion.w;
}
if (property === 'intensity') {
this.instance.intensity = this.intensity;
}
if (property === 'color') {
this.instance.color.set(this.color.toHex());
}
};
/**
* Converts a GameLib.D3.Light to a GameLib.D3.API.Light
* @returns {GameLib.D3.API.Light}
*/
GameLib.D3.Light.prototype.toApiObject = function() {
return new GameLib.D3.API.Light(
this.id,
this.lightType,
this.name,
this.color.toApiObject(),
this.intensity,
this.position.toApiObject(),
this.targetPosition.toApiObject(),
this.quaternion.toApiObject(),
this.rotation.toApiObject(),
this.scale.toApiObject(),
this.distance,
this.decay,
this.power,
this.angle,
this.penumbra,
GameLib.Utils.IdOrNull(this.parentScene),
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Returns a new GameLib.D3.Light from a GameLib.D3.API.Light
* @param graphics GameLib.D3.Graphics
* @param objectLight GameLib.D3.API.Light
* @returns {GameLib.D3.Light}
*/
GameLib.D3.Light.FromObject = function(graphics, objectLight) {
return new GameLib.D3.Light(
graphics,
GameLib.D3.API.Light.FromObject(objectLight)
);
};
/**
* Entities with LookAt component looks to targetPosition (default up is 0,1,0)
* @param graphics GameLib.D3.Graphics
* @param apiLookAt GameLib.D3.API.LookAt
* @constructor
*/
GameLib.D3.LookAt = function (
graphics,
apiLookAt
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiLookAt)) {
apiLookAt = {};
}
if (apiLookAt instanceof GameLib.D3.LookAt) {
return apiLookAt;
}
GameLib.D3.API.LookAt.call(
this,
apiLookAt.id,
apiLookAt.name,
apiLookAt.currentComponent,
apiLookAt.targetComponent,
apiLookAt.targetPositionOffset,
apiLookAt.rotationSpeed,
apiLookAt.parentEntity
);
this.targetPositionOffset = new GameLib.Vector3(
this.graphics,
this.targetPositionOffset,
this
);
this.lookAtMatrix = new GameLib.Matrix4(
this.graphics,
this.lookAtMatrix,
this
);
this.up = new GameLib.Vector3(
this.graphics,
this.up,
this
);
this.currentRotation = new GameLib.Quaternion(
this.graphics,
this.currentRotation,
this
);
this.targetPosition = new GameLib.Vector3(
this.graphics,
this.targetPosition,
this
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_LOOK_AT,
{
'currentComponent' : GameLib.Component,
'targetComponent' : GameLib.Component
}
);
};
GameLib.D3.LookAt.prototype = Object.create(GameLib.D3.API.LookAt.prototype);
GameLib.D3.LookAt.prototype.constructor = GameLib.D3.LookAt;
GameLib.D3.LookAt.prototype.createInstance = function() {
this.instance = true;
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.LookAt.prototype.updateInstance = function() {
};
/**
* to API object
* @returns {GameLib.D3.API.LookAt}
*/
GameLib.D3.LookAt.prototype.toApiObject = function() {
var apiLookAt = new GameLib.D3.API.LookAt(
this.id,
this.name,
GameLib.Utils.IdOrNull(this.currentComponent),
GameLib.Utils.IdOrNull(this.targetComponent),
this.targetPositionOffset.toApiObject(),
this.rotationSpeed,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiLookAt;
};
GameLib.D3.LookAt.FromObject = function(graphics, objectComponent) {
var apiLookAt = GameLib.D3.API.LookAt.FromObject(objectComponent);
return new GameLib.D3.LookAt(
graphics,
apiLookAt
);
};
/**
* Looks at using time
* @param deltaTime
*/
GameLib.D3.LookAt.prototype.update = function(deltaTime) {
if (this.currentComponent && this.targetComponent) {
this.targetPosition.x = this.targetComponent.position.x + this.targetPositionOffset.x;
this.targetPosition.y = this.targetComponent.position.y + this.targetPositionOffset.y;
this.targetPosition.z = this.targetComponent.position.z + this.targetPositionOffset.z;
this.targetPosition.updateInstance();
// this.lookAtMatrix.lookAt(
// this.currentComponent.position,
// this.targetPosition,
// this.up
// );
//
// this.currentRotation = new GameLib.Quaternion(this.graphics, this, new GameLib.API.Quaternion());
//
// this.currentRotation.setFromRotationMatrix(this.lookAtMatrix);
// var t = deltaTime * this.rotationSpeed;
// t = t * t * t * (t * (6.0 * t - 15.0) + 10.0);
// this.currentRotation.slerp(this.currentRotation, t);
// this.currentRotation.normalize();
//
// this.currentComponent.quaternion.x = this.currentRotation.x;
// this.currentComponent.quaternion.y = this.currentRotation.y;
// this.currentComponent.quaternion.z = this.currentRotation.z;
// this.currentComponent.quaternion.w = this.currentRotation.w;
//
this.currentComponent.lookAt.x = this.targetPosition.x;
this.currentComponent.lookAt.y = this.targetPosition.y;
this.currentComponent.lookAt.z = this.targetPosition.z;
this.currentComponent.lookAt.updateInstance();
}
};
/**
* Material Superset - The apiMaterial properties get moved into the Material object itself, and then the instance is
* created
* @param graphics GameLib.D3.Graphics
* @param apiMaterial GameLib.D3.API.Material
* @constructor
* @returns {GameLib.D3.Material | GameLib.D3.API.Material}
*/
GameLib.D3.Material = function(
graphics,
apiMaterial
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMaterial)) {
apiMaterial = {};
}
if (apiMaterial instanceof GameLib.D3.Material) {
return apiMaterial;
}
GameLib.D3.API.Material.call(
this,
apiMaterial.id,
apiMaterial.materialType,
apiMaterial.name,
apiMaterial.opacity,
apiMaterial.side,
apiMaterial.transparent,
apiMaterial.specular,
apiMaterial.lightMapIntensity,
apiMaterial.aoMapIntensity,
apiMaterial.color,
apiMaterial.emissive,
apiMaterial.emissiveIntensity,
apiMaterial.combine,
apiMaterial.shininess,
apiMaterial.reflectivity,
apiMaterial.refractionRatio,
apiMaterial.fog,
apiMaterial.wireframe,
apiMaterial.wireframeLineWidth,
apiMaterial.wireframeLineCap,
apiMaterial.wireframeLineJoin,
apiMaterial.vertexColors,
apiMaterial.skinning,
apiMaterial.morphTargets,
apiMaterial.morphNormals,
apiMaterial.lineWidth,
apiMaterial.lineCap,
apiMaterial.lineJoin,
apiMaterial.dashSize,
apiMaterial.gapWidth,
apiMaterial.blending,
apiMaterial.blendSrc,
apiMaterial.blendDst,
apiMaterial.blendEquation,
apiMaterial.depthTest,
apiMaterial.depthFunc,
apiMaterial.depthWrite,
apiMaterial.polygonOffset,
apiMaterial.polygonOffsetFactor,
apiMaterial.polygonOffsetUnits,
apiMaterial.alphaTest,
apiMaterial.clippingPlanes,
apiMaterial.clipShadows,
apiMaterial.visible,
apiMaterial.overdraw,
apiMaterial.flatShading,
apiMaterial.bumpScale,
apiMaterial.normalScale,
apiMaterial.displacementScale,
apiMaterial.displacementBias,
apiMaterial.roughness,
apiMaterial.metalness,
apiMaterial.pointSize,
apiMaterial.pointSizeAttenuation,
apiMaterial.spriteRotation,
apiMaterial.envMapIntensity,
apiMaterial.alphaMap,
apiMaterial.aoMap,
apiMaterial.bumpMap,
apiMaterial.diffuseMap,
apiMaterial.displacementMap,
apiMaterial.emissiveMap,
apiMaterial.environmentMap,
apiMaterial.lightMap,
apiMaterial.metalnessMap,
apiMaterial.normalMap,
apiMaterial.roughnessMap,
apiMaterial.specularMap,
apiMaterial.parentEntity
);
this.specular = new GameLib.Color(
graphics,
this.specular,
this
);
this.color = new GameLib.Color(
graphics,
this.color,
this
);
this.emissive = new GameLib.Color(
graphics,
this.emissive,
this
);
if (this.alphaMap) {
if (this.alphaMap instanceof GameLib.D3.API.Texture) {
this.alphaMap = new GameLib.D3.Texture(
this.graphics,
this.alphaMap
);
}
}
if (this.aoMap) {
if (this.aoMap instanceof GameLib.D3.API.Texture) {
this.aoMap = new GameLib.D3.Texture(
this.graphics,
this.aoMap
);
}
}
if (this.bumpMap) {
if (this.bumpMap instanceof GameLib.D3.API.Texture) {
this.bumpMap = new GameLib.D3.Texture(
this.graphics,
this.bumpMap
);
}
}
if (this.diffuseMap) {
if (this.diffuseMap instanceof GameLib.D3.API.Texture) {
this.diffuseMap = new GameLib.D3.Texture(
this.graphics,
this.diffuseMap
);
}
}
if (this.displacementMap) {
if (this.displacementMap instanceof GameLib.D3.API.Texture) {
this.displacementMap = new GameLib.D3.Texture(
this.graphics,
this.displacementMap
);
}
}
if (this.emissiveMap) {
if (this.emissiveMap instanceof GameLib.D3.API.Texture) {
this.emissiveMap = new GameLib.D3.Texture(
this.graphics,
this.emissiveMap
);
}
}
if (this.environmentMap) {
if (this.environmentMap instanceof GameLib.D3.API.Texture) {
this.environmentMap = new GameLib.D3.Texture(
this.graphics,
this.environmentMap
);
}
}
if (this.lightMap) {
if (this.lightMap instanceof GameLib.D3.API.Texture) {
this.lightMap = new GameLib.D3.Texture(
this.graphics,
this.lightMap
);
}
}
if (this.metalnessMap) {
if (this.metalnessMap instanceof GameLib.D3.API.Texture) {
this.metalnessMap = new GameLib.D3.Texture(
this.graphics,
this.metalnessMap
);
}
}
if (this.normalMap) {
if (this.normalMap instanceof GameLib.D3.API.Texture) {
this.normalMap = new GameLib.D3.Texture(
this.graphics,
this.normalMap
);
}
}
if (this.roughnessMap) {
if (this.roughnessMap instanceof GameLib.D3.API.Texture) {
this.roughnessMap = new GameLib.D3.Texture(
this.graphics,
this.roughnessMap
);
}
}
if (this.specularMap) {
if (this.specularMap instanceof GameLib.D3.API.Texture) {
this.specularMap = new GameLib.D3.Texture(
this.graphics,
this.specularMap
);
}
}
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_MATERIAL,
{
'alphaMap' : GameLib.D3.Texture,
'aoMap' : GameLib.D3.Texture,
'bumpMap' : GameLib.D3.Texture,
'diffuseMap' : GameLib.D3.Texture,
'displacementMap' : GameLib.D3.Texture,
'emissiveMap' : GameLib.D3.Texture,
'environmentMap' : GameLib.D3.Texture,
'lightMap' : GameLib.D3.Texture,
'metalnessMap' : GameLib.D3.Texture,
'normalMap' : GameLib.D3.Texture,
'roughnessMap' : GameLib.D3.Texture,
'specularMap' : GameLib.D3.Texture
}
);
};
GameLib.D3.Material.prototype = Object.create(GameLib.D3.API.Material.prototype);
GameLib.D3.Material.prototype.constructor = GameLib.D3.Material;
/**
* Combine Method
* @type {number}
*/
GameLib.D3.Material.TYPE_MULTIPLY_OPERATION = 0;
GameLib.D3.Material.TYPE_MIX_OPERATION = 1;
GameLib.D3.Material.TYPE_ADD_OPERATION = 2;
/**
* Vertex Color Mode
* @type {number}
*/
GameLib.D3.Material.TYPE_NO_COLORS = 0;
GameLib.D3.Material.TYPE_FACE_COLORS = 1;
GameLib.D3.Material.TYPE_VERTEX_COLORS = 2;
/**
* Blending Mode
* @type {number}
*/
GameLib.D3.Material.TYPE_NO_BLENDING = 0;
GameLib.D3.Material.TYPE_NORMAL_BLENDING = 1;
GameLib.D3.Material.TYPE_ADDITIVE_BLENDING = 2;
GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING = 3;
GameLib.D3.Material.TYPE_MULTIPLY_BLENDING = 4;
GameLib.D3.Material.TYPE_CUSTOM_BLENDING = 5;
/**
* Blend Source and Destination
* @type {number}
*/
GameLib.D3.Material.TYPE_ZERO_FACTOR = 200;
GameLib.D3.Material.TYPE_ONE_FACTOR = 201;
GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR = 202;
GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR = 203;
GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR = 204;
GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR = 205;
GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR = 206;
GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR = 207;
GameLib.D3.Material.TYPE_DST_COLOR_FACTOR = 208;
GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR = 209;
GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR = 210;
/**
* Blend Operation
* @type {number}
*/
GameLib.D3.Material.TYPE_ADD_EQUATION = 100;
GameLib.D3.Material.TYPE_SUBTRACT_EQUATION = 101;
GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION = 102;
GameLib.D3.Material.TYPE_MIN_EQUATION = 103;
GameLib.D3.Material.TYPE_MAX_EQUATION = 104;
/**
* Depth Function
* @type {number}
*/
GameLib.D3.Material.TYPE_NEVER_DEPTH = 0;
GameLib.D3.Material.TYPE_ALWAYS_DEPTH = 1;
GameLib.D3.Material.TYPE_LESS_DEPTH = 2;
GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH = 3;
GameLib.D3.Material.TYPE_EQUAL_DEPTH = 4;
GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH = 5;
GameLib.D3.Material.TYPE_GREATER_DEPTH = 6;
GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH = 7;
/**
* Culling Mode
* @type {number}
*/
GameLib.D3.Material.TYPE_FRONT_SIDE = 0;
GameLib.D3.Material.TYPE_BACK_SIDE = 1;
GameLib.D3.Material.TYPE_DOUBLE_SIDE = 2;
/**
* Shading Type
* @type {number}
*/
GameLib.D3.Material.TYPE_FLAT_SHADING = 1;
GameLib.D3.Material.TYPE_SMOOTH_SHADING = 2;
/**
* Material Type
* @type {string}
*/
GameLib.D3.Material.MATERIAL_TYPE_LINE_BASIC = 0x1;
GameLib.D3.Material.MATERIAL_TYPE_LINE_DASHED = 0x2;
GameLib.D3.Material.MATERIAL_TYPE_BASIC = 0x3;
GameLib.D3.Material.MATERIAL_TYPE_DEPTH = 0x4;
GameLib.D3.Material.MATERIAL_TYPE_LAMBERT = 0x5;
GameLib.D3.Material.MATERIAL_TYPE_NORMAL = 0x6;
GameLib.D3.Material.MATERIAL_TYPE_PHONG = 0x7;
GameLib.D3.Material.MATERIAL_TYPE_STANDARD = 0x8;
GameLib.D3.Material.MATERIAL_TYPE_POINTS = 0x9;
GameLib.D3.Material.MATERIAL_TYPE_SPRITE = 0xa;
GameLib.D3.Material.MATERIAL_TYPE_TOON = 0xb;
GameLib.D3.Material.LINE_CAP_BUTT = 0x1;//'butt';
GameLib.D3.Material.LINE_CAP_ROUND = 0x2;//'round';
GameLib.D3.Material.LINE_CAP_SQUARE = 0x3;//'square';
GameLib.D3.Material.LINE_JOIN_ROUND = 0x1;//'round';
GameLib.D3.Material.LINE_JOIN_BEVEL = 0x2;//'bevel';
GameLib.D3.Material.LINE_JOIN_MITER = 0x3;//'miter';
GameLib.D3.Material.prototype.createToonMaterialInstance = function() {
return new THREE.MeshToonMaterial({
name: this.name,
opacity: this.opacity,
transparent: this.transparent,
blending: this.blending,
blendSrc: this.blendSrc,
blendDst: this.blendDst,
blendEquation: this.blendEquation,
depthTest: this.depthTest,
depthFunc: this.depthFunc,
depthWrite: this.depthWrite,
polygonOffset: this.polygonOffset,
polygonOffsetFactor: this.polygonOffsetFactor,
polygonOffsetUnits: this.polygonOffsetUnits,
alphaTest: this.alphaTest,
clippingPlanes: this.clippingPlanes,
clipShadows: this.clipShadows,
overdraw: this.overdraw,
visible: this.visible,
side: this.side,
color: this.color.instance,
roughness: this.roughness,
metalness: this.metalness,
lightMapIntensity: this.lightMapIntensity,
aoMapIntensity: this.aoMapIntensity,
emissive: this.emissive.instance,
emissiveIntensity: this.emissiveIntensity,
bumpScale: this.bumpScale,
normalScale: this.normalScale,
displacementScale: this.displacementScale,
refractionRatio: this.refractionRatio,
fog: this.fog,
flatShading: this.flatShading,
wireframe: this.wireframe,
wireframeLinewidth: this.wireframeLineWidth,
wireframeLinecap: this.wireframeLineCap,
wireframeLinejoin: this.wireframeLineJoin,
vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS,
skinning: this.skinning,
morphTargets: this.morphTargets,
morphNormals: this.morphNormals
});
};
GameLib.D3.Material.prototype.createStandardMaterialInstance = function() {
return new THREE.MeshStandardMaterial({
name: this.name,
opacity: this.opacity,
transparent: this.transparent,
blending: this.blending,
blendSrc: this.blendSrc,
blendDst: this.blendDst,
blendEquation: this.blendEquation,
depthTest: this.depthTest,
depthFunc: this.depthFunc,
depthWrite: this.depthWrite,
polygonOffset: this.polygonOffset,
polygonOffsetFactor: this.polygonOffsetFactor,
polygonOffsetUnits: this.polygonOffsetUnits,
alphaTest: this.alphaTest,
clippingPlanes: this.clippingPlanes,
clipShadows: this.clipShadows,
overdraw: this.overdraw,
visible: this.visible,
side: this.side,
color: this.color.instance,
roughness: this.roughness,
metalness: this.metalness,
lightMapIntensity: this.lightMapIntensity,
aoMapIntensity: this.aoMapIntensity,
emissive: this.emissive.instance,
emissiveIntensity: this.emissiveIntensity,
bumpScale: this.bumpScale,
normalScale: this.normalScale,
displacementScale: this.displacementScale,
refractionRatio: this.refractionRatio,
fog: this.fog,
flatShading: this.flatShading,
wireframe: this.wireframe,
wireframeLinewidth: this.wireframeLineWidth,
wireframeLinecap: this.wireframeLineCap,
wireframeLinejoin: this.wireframeLineJoin,
vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS,
skinning: this.skinning,
morphTargets: this.morphTargets,
morphNormals: this.morphNormals
});
};
GameLib.D3.Material.prototype.createPointsMaterialInstance = function() {
return new THREE.PointsMaterial({
name: this.name,
opacity: this.opacity,
transparent: this.transparent,
// blending: this.blending,
// blendSrc: this.blendSrc,
// blendDst: this.blendDst,
// blendEquation: this.blendEquation,
depthTest: this.depthTest,
depthFunc: this.depthFunc,
depthWrite: this.depthWrite,
// polygonOffset: this.polygonOffset,
// polygonOffsetFactor: this.polygonOffsetFactor,
// polygonOffsetUnits: this.polygonOffsetUnits,
// alphaTest: this.alphaTest,
// clippingPlanes: this.clippingPlanes,
// clipShadows: this.clipShadows,
// overdraw: this.overdraw,
visible: this.visible,
side: this.side,
color: this.color.instance,
size: this.pointSize,
sizeAttenuation: this.pointSizeAttenuation
// vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS,
// fog: this.fog
});
};
GameLib.D3.Material.prototype.createLineBasicMaterialInstance = function() {
var linecap = 'round';
if (this.lineCap === GameLib.D3.Material.LINE_CAP_BUTT) {
linecap = 'butt';
}
if (this.lineCap === GameLib.D3.Material.LINE_CAP_SQUARE) {
linecap = 'square';
}
var linejoin = 'round';
if (this.lineJoin === GameLib.D3.Material.LINE_JOIN_BEVEL) {
linejoin = 'bevel';
}
if (this.lineJoin === GameLib.D3.Material.LINE_JOIN_MITER) {
linejoin = 'miter';
}
return new THREE.LineBasicMaterial({
name: this.name,
opacity: this.opacity,
transparent: this.transparent,
// blending: this.blending,
// blendSrc: this.blendSrc,
// blendDst: this.blendDst,
// blendEquation: this.blendEquation,
depthTest: this.depthTest,
depthFunc: this.depthFunc,
depthWrite: this.depthWrite,
// polygonOffset: this.polygonOffset,
// polygonOffsetFactor: this.polygonOffsetFactor,
// polygonOffsetUnits: this.polygonOffsetUnits,
// alphaTest: this.alphaTest,
// clippingPlanes: this.clippingPlanes,
// clipShadows: this.clipShadows,
// overdraw: this.overdraw,
visible: this.visible,
side: this.side,
color: this.color.instance,
linewidth: this.lineWidth,
linecap: linecap,
linejoin: linejoin
// vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS,
// fog: this.fog
});
};
GameLib.D3.Material.prototype.createPhongMaterialInstance = function() {
return new THREE.MeshPhongMaterial({
name: this.name,
opacity: this.opacity,
transparent: this.transparent,
blending: this.blending,
blendSrc: this.blendSrc,
blendDst: this.blendDst,
blendEquation: this.blendEquation,
depthTest: this.depthTest,
depthFunc: this.depthFunc,
depthWrite: this.depthWrite,
polygonOffset: this.polygonOffset,
polygonOffsetFactor: this.polygonOffsetFactor,
polygonOffsetUnits: this.polygonOffsetUnits,
alphaTest: this.alphaTest,
clippingPlanes: this.clippingPlanes,
clipShadows: this.clipShadows,
overdraw: this.overdraw,
visible: this.visible,
side: this.side,
color: this.color.instance,
specular: this.specular.instance,
shininess: this.shininess,
lightMapIntensity: this.lightMapIntensity,
aoMapIntensity: this.aoMapIntensity,
emissive: this.emissive.instance,
emissiveIntensity: this.emissiveIntensity,
bumpScale: this.bumpScale,
normalScale: this.normalScale,
displacementScale: this.displacementScale,
combine: this.combine,
refractionRatio: this.refractionRatio,
fog: this.fog,
flatShading: this.flatShading,
wireframe: this.wireframe,
wireframeLinewidth: this.wireframeLineWidth,
wireframeLinecap: this.wireframeLineCap,
wireframeLinejoin: this.wireframeLineJoin,
vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS,
skinning: this.skinning,
morphTargets: this.morphTargets,
morphNormals: this.morphNormals
});
};
GameLib.D3.Material.prototype.createMeshBasicMaterialInstance = function() {
return new THREE.MeshBasicMaterial({
name: this.name,
opacity: this.opacity,
transparent: this.transparent,
blending: this.blending,
blendSrc: this.blendSrc,
blendDst: this.blendDst,
blendEquation: this.blendEquation,
depthTest: this.depthTest,
depthFunc: this.depthFunc,
depthWrite: this.depthWrite,
polygonOffset: this.polygonOffset,
polygonOffsetFactor: this.polygonOffsetFactor,
polygonOffsetUnits: this.polygonOffsetUnits,
alphaTest: this.alphaTest,
clippingPlanes: this.clippingPlanes,
clipShadows: this.clipShadows,
overdraw: this.overdraw,
visible: this.visible,
side: this.side,
color: this.color.instance,
vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS,
fog: this.fog
});
};
GameLib.D3.Material.prototype.checkTexture = function(runtimeMap, instanceMap) {
var textureChanged = false;
if (this[runtimeMap] && this[runtimeMap].instance) {
if (this.instance[instanceMap] !== this[runtimeMap].instance) {
this.instance[instanceMap] = this[runtimeMap].instance;
textureChanged = true;
}
} else {
if (this.instance[instanceMap] !== null) {
this.instance[instanceMap] = null;
textureChanged = true;
}
}
return textureChanged;
};
/**
* updates textures
*/
GameLib.D3.Material.prototype.updateTextures = function() {
var textureChanged = false;
if (this.checkTexture('alphaMap', 'alphaMap')) {
textureChanged = true;
}
if (this.checkTexture('aoMap', 'aoMap')) {
textureChanged = true;
}
if (this.checkTexture('bumpMap', 'bumpMap')) {
textureChanged = true;
}
if (this.checkTexture('diffuseMap', 'map')) {
textureChanged = true;
}
if (this.checkTexture('displacementMap', 'displacementMap')) {
textureChanged = true;
}
if (this.checkTexture('emissiveMap', 'emissiveMap')) {
textureChanged = true;
}
if (this.checkTexture('environmentMap', 'envMap')) {
textureChanged = true;
}
if (this.checkTexture('lightMap', 'lightMap')) {
textureChanged = true;
}
if (this.checkTexture('metalnessMap', 'metalnessMap')) {
textureChanged = true;
}
if (this.checkTexture('normalMap', 'normalMap')) {
textureChanged = true;
}
if (this.checkTexture('roughnessMap', 'roughnessMap')) {
textureChanged = true;
}
if (this.checkTexture('specularMap', 'specularMap')) {
textureChanged = true;
}
if (textureChanged) {
this.publish(
GameLib.Event.MATERIAL_TEXTURES_UPDATED,
{
material : this
}
);
}
return textureChanged;
};
GameLib.D3.Material.prototype.updateToonMaterialInstance = function(property) {
this.instance.name = this.name;
this.instance.opacity = this.opacity;
this.instance.transparent = this.transparent;
this.instance.blending = this.blending;
this.instance.blendSrc = this.blendSrc;
this.instance.blendDst = this.blendDst;
this.instance.blendEquation = this.blendEquation;
this.instance.depthTest = this.depthTest;
this.instance.depthFunc = this.depthFunc;
this.instance.depthWrite = this.depthWrite;
this.instance.polygonOffset = this.polygonOffset;
this.instance.polygonOffsetFactor = this.polygonOffsetFactor;
this.instance.polygonOffsetUnits = this.polygonOffsetUnits;
this.instance.alphaTest = this.alphaTest;
this.instance.clippingPlanes = this.clippingPlanes;
this.instance.clipShadows = this.clipShadows;
this.instance.overdraw = this.overdraw;
this.instance.visible = this.visible;
this.instance.side = this.side;
this.instance.color = this.color.instance;
this.instance.envMapIntensity = this.envMapIntensity; //standard material doesnt have specular color
this.instance.roughness = this.roughness;
this.instance.metalness = this.metalness;
this.instance.lightMapIntensity = this.lightMapIntensity;
this.instance.aoMapIntensity = this.aoMapIntensity;
this.instance.emissive = this.emissive.instance;
this.instance.emissiveIntensity = this.emissiveIntensity;
this.instance.bumpScale = this.bumpScale;
this.instance.normalScale = this.normalScale;
this.instance.displacementScale = this.displacementScale;
this.instance.refractionRatio = this.refractionRatio;
this.instance.fog = this.fog;
this.instance.flatShading = this.flatShading;
this.instance.wireframe = this.wireframe;
this.instance.wireframeLinewidth = this.wireframeLineWidth;
this.instance.wireframeLinecap = this.wireframeLineCap;
this.instance.wireframeLinejoin = this.wireframeLineJoin;
this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS;
this.instance.skinning = this.skinning;
this.instance.morphTargets = this.morphTargets;
this.instance.morphNormals = this.morphNormals;
};
GameLib.D3.Material.prototype.updateStandardMaterialInstance = function(property) {
this.instance.name = this.name;
this.instance.opacity = this.opacity;
this.instance.transparent = this.transparent;
this.instance.blending = this.blending;
this.instance.blendSrc = this.blendSrc;
this.instance.blendDst = this.blendDst;
this.instance.blendEquation = this.blendEquation;
this.instance.depthTest = this.depthTest;
this.instance.depthFunc = this.depthFunc;
this.instance.depthWrite = this.depthWrite;
this.instance.polygonOffset = this.polygonOffset;
this.instance.polygonOffsetFactor = this.polygonOffsetFactor;
this.instance.polygonOffsetUnits = this.polygonOffsetUnits;
this.instance.alphaTest = this.alphaTest;
this.instance.clippingPlanes = this.clippingPlanes;
this.instance.clipShadows = this.clipShadows;
this.instance.overdraw = this.overdraw;
this.instance.visible = this.visible;
this.instance.side = this.side;
this.instance.color = this.color.instance;
this.instance.envMapIntensity = this.envMapIntensity; //standard material doesnt have specular color
this.instance.roughness = this.roughness;
this.instance.metalness = this.metalness;
this.instance.lightMapIntensity = this.lightMapIntensity;
this.instance.aoMapIntensity = this.aoMapIntensity;
this.instance.emissive = this.emissive.instance;
this.instance.emissiveIntensity = this.emissiveIntensity;
this.instance.bumpScale = this.bumpScale;
this.instance.normalScale = this.normalScale;
this.instance.displacementScale = this.displacementScale;
this.instance.refractionRatio = this.refractionRatio;
this.instance.fog = this.fog;
this.instance.flatShading = this.flatShading;
this.instance.wireframe = this.wireframe;
this.instance.wireframeLinewidth = this.wireframeLineWidth;
this.instance.wireframeLinecap = this.wireframeLineCap;
this.instance.wireframeLinejoin = this.wireframeLineJoin;
this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS;
this.instance.skinning = this.skinning;
this.instance.morphTargets = this.morphTargets;
this.instance.morphNormals = this.morphNormals;
};
GameLib.D3.Material.prototype.updatePointsMaterialInstance = function(property) {
this.instance.name = this.name;
this.instance.opacity = this.opacity;
this.instance.transparent = this.transparent;
// this.instance.blending = this.blending;
// this.instance.blendSrc = this.blendSrc;
// this.instance.blendDst = this.blendDst;
// this.instance.blendEquation = this.blendEquation;
// this.instance.depthTest = this.depthTest;
this.instance.depthFunc = this.depthFunc;
this.instance.depthWrite = this.depthWrite;
// this.instance.polygonOffset = this.polygonOffset;
// this.instance.polygonOffsetFactor = this.polygonOffsetFactor;
// this.instance.polygonOffsetUnits = this.polygonOffsetUnits;
// this.instance.alphaTest = this.alphaTest;
// this.instance.clippingPlanes = this.clippingPlanes;
// this.instance.clipShadows = this.clipShadows;
// this.instance.overdraw = this.overdraw;
this.instance.visible = this.visible;
this.instance.side = this.side;
this.instance.color = this.color.instance;
this.instance.size = this.pointSize;
this.instance.sizeAttenuation = this.pointSizeAttenuation;
//this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS;
//this.instance.fog = this.fog;
};
GameLib.D3.Material.prototype.updateLineBasicMaterialInstance = function(property) {
var linecap = 'round';
if (this.lineCap === GameLib.D3.Material.LINE_CAP_BUTT) {
linecap = 'butt';
}
if (this.lineCap === GameLib.D3.Material.LINE_CAP_SQUARE) {
linecap = 'square';
}
var linejoin = 'round';
if (this.lineJoin === GameLib.D3.Material.LINE_JOIN_BEVEL) {
linejoin = 'bevel';
}
if (this.lineJoin === GameLib.D3.Material.LINE_JOIN_MITER) {
linejoin = 'miter';
}
this.instance.name = this.name;
this.instance.opacity = this.opacity;
this.instance.transparent = this.transparent;
// this.instance.blending = this.blending;
// this.instance.blendSrc = this.blendSrc;
// this.instance.blendDst = this.blendDst;
// this.instance.blendEquation = this.blendEquation;
// this.instance.depthTest = this.depthTest;
this.instance.depthFunc = this.depthFunc;
this.instance.depthWrite = this.depthWrite;
// this.instance.polygonOffset = this.polygonOffset;
// this.instance.polygonOffsetFactor = this.polygonOffsetFactor;
// this.instance.polygonOffsetUnits = this.polygonOffsetUnits;
// this.instance.alphaTest = this.alphaTest;
// this.instance.clippingPlanes = this.clippingPlanes;
// this.instance.clipShadows = this.clipShadows;
// this.instance.overdraw = this.overdraw;
this.instance.visible = this.visible;
this.instance.side = this.side;
this.instance.color = this.color.instance;
this.instance.linewidth = this.lineWidth;
this.instance.linecap = linecap;
this.instance.linejoin = linejoin;
//this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS;
//this.instance.fog = this.fog;
};
GameLib.D3.Material.prototype.updatePhongMaterialInstance = function(property) {
this.instance.name = this.name;
this.instance.opacity = this.opacity;
this.instance.transparent = this.transparent;
this.instance.blending = this.blending;
this.instance.blendSrc = this.blendSrc;
this.instance.blendDst = this.blendDst;
this.instance.blendEquation = this.blendEquation;
this.instance.depthTest = this.depthTest;
this.instance.depthFunc = this.depthFunc;
this.instance.depthWrite = this.depthWrite;
this.instance.polygonOffset = this.polygonOffset;
this.instance.polygonOffsetFactor = this.polygonOffsetFactor;
this.instance.polygonOffsetUnits = this.polygonOffsetUnits;
this.instance.alphaTest = this.alphaTest;
this.instance.clippingPlanes = this.clippingPlanes;
this.instance.clipShadows = this.clipShadows;
this.instance.overdraw = this.overdraw;
this.instance.visible = this.visible;
this.instance.side = this.side;
this.instance.color = this.color.instance;
this.instance.specular = this.specular.instance;
this.instance.shininess = this.shininess;
this.instance.lightMapIntensity = this.lightMapIntensity;
this.instance.aoMapIntensity = this.aoMapIntensity;
this.instance.emissive = this.emissive.instance;
this.instance.emissiveIntensity = this.emissiveIntensity;
this.instance.envMapIntensity = this.envMapIntensity;
this.instance.bumpScale = this.bumpScale;
this.instance.normalScale = this.normalScale;
this.instance.displacementScale = this.displacementScale;
this.instance.combine = this.combine;
this.instance.refractionRatio = this.refractionRatio;
this.instance.fog = this.fog;
this.instance.flatShading = this.flatShading;
this.instance.wireframe = this.wireframe;
this.instance.wireframeLinewidth = this.wireframeLineWidth;
this.instance.wireframeLinecap = this.wireframeLineCap;
this.instance.wireframeLinejoin = this.wireframeLineJoin;
this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS;
this.instance.skinning = this.skinning;
this.instance.morphTargets = this.morphTargets;
this.instance.morphNormals = this.morphNormals;
};
GameLib.D3.Material.prototype.updateMeshBasicMaterialInstance = function(property) {
this.instance.name = this.name;
this.instance.opacity = this.opacity;
this.instance.transparent = this.transparent;
this.instance.blending = this.blending;
this.instance.blendSrc = this.blendSrc;
this.instance.blendDst = this.blendDst;
this.instance.blendEquation = this.blendEquation;
this.instance.depthTest = this.depthTest;
this.instance.depthFunc = this.depthFunc;
this.instance.depthWrite = this.depthWrite;
this.instance.polygonOffset = this.polygonOffset;
this.instance.polygonOffsetFactor = this.polygonOffsetFactor;
this.instance.polygonOffsetUnits = this.polygonOffsetUnits;
this.instance.alphaTest = this.alphaTest;
this.instance.clippingPlanes = this.clippingPlanes;
this.instance.clipShadows = this.clipShadows;
this.instance.overdraw = this.overdraw;
this.instance.visible = this.visible;
this.instance.side = this.side;
this.instance.color = this.color.instance;
this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS;
this.instance.fog = this.fog;
};
/**
* Material instance
* @returns {*}
*/
GameLib.D3.Material.prototype.createInstance = function() {
if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_STANDARD) {
this.instance = this.createStandardMaterialInstance();
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_POINTS) {
this.instance = this.createPointsMaterialInstance();
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_PHONG) {
this.instance = this.createPhongMaterialInstance();
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_BASIC) {
this.instance = this.createMeshBasicMaterialInstance();
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_LINE_BASIC) {
this.instance = this.createLineBasicMaterialInstance();
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_TOON) {
this.instance = this.createToonMaterialInstance();
} else {
console.warn("material type is not implemented yet: " + this.materialType);
}
this.instance.needsUpdate = true;
this.updateTextures();
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Material.prototype.updateInstance = function(property) {
if (!this.instance) {
console.warn('Attempt to update a non-existent instance');
return;
}
if (property === 'materialType') {
this.createInstance();
this.publish(
GameLib.Event.MATERIAL_TYPE_CHANGED,
{
material: this
}
);
return;
}
if (
property === 'alphaMap' ||
property === 'aoMap' ||
property === 'bumpMap' ||
property === 'diffuseMap' ||
property === 'displacementMap' ||
property === 'emissiveMap' ||
property === 'environmentMap' ||
property === 'lightMap' ||
property === 'metalnessMap' ||
property === 'normalMap' ||
property === 'roughnessMap' ||
property === 'specularMap'
) {
this.updateTextures();
}
if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_STANDARD) {
this.updateStandardMaterialInstance(property);
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_POINTS) {
this.updatePointsMaterialInstance(property);
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_PHONG) {
this.updatePhongMaterialInstance(property);
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_BASIC) {
this.updateMeshBasicMaterialInstance(property);
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_LINE_BASIC) {
this.updateLineBasicMaterialInstance(property);
} else if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_TOON) {
this.updateToonMaterialInstance(property);
} else {
console.warn('not yet implemented (material type = ' + this.materialType + ')');
}
this.instance.needsUpdate = true;
};
/**
* Converts a GameLib.D3.Material to a GameLib.D3.API.Material
* @returns {GameLib.D3.API.Material}
*/
GameLib.D3.Material.prototype.toApiObject = function(save) {
if (GameLib.Utils.UndefinedOrNull(save)) {
save = false;
}
var apiAlphaMap = null;
if (this.alphaMap) {
if (save) {
this.alphaMap.save();
}
apiAlphaMap = this.alphaMap.id;
}
var apiAoMap = null;
if (this.aoMap) {
if (save) {
this.aoMap.save();
}
apiAoMap = this.aoMap.id;
}
var apiBumpMap = null;
if (this.bumpMap) {
if (save) {
this.bumpMap.save();
}
apiBumpMap = this.bumpMap.id;
}
var apiDiffuseMap = null;
if (this.diffuseMap) {
if (save) {
this.diffuseMap.save();
}
apiDiffuseMap = this.diffuseMap.id;
}
var apiDisplacementMap = null;
if (this.displacementMap) {
if (save) {
this.displacementMap.save();
}
apiDisplacementMap = this.displacementMap.id;
}
var apiEmissiveMap = null;
if (this.emissiveMap) {
if (save) {
this.emissiveMap.save();
}
apiEmissiveMap = this.emissiveMap.id;
}
var apiEnvironmentMap = null;
if (this.environmentMap) {
if (save) {
this.environmentMap.save();
}
apiEnvironmentMap = this.environmentMap.id;
}
var apiLightMap = null;
if (this.lightMap) {
if (save) {
this.lightMap.save();
}
apiLightMap = this.lightMap.id;
}
var apiMetalnessMap = null;
if (this.metalnessMap) {
if (save) {
this.metalnessMap.save();
}
apiMetalnessMap = this.metalnessMap.id;
}
var apiNormalMap = null;
if (this.normalMap) {
this.normalMap.save();
apiNormalMap = this.normalMap.id;
}
var apiRoughnessMap = null;
if (this.roughnessMap) {
if (save) {
this.roughnessMap.save();
}
apiRoughnessMap = this.roughnessMap.id;
}
var apiSpecularMap = null;
if (this.specularMap) {
if (save) {
this.specularMap.save();
}
apiSpecularMap = this.specularMap.id;
}
var apiMaterial = new GameLib.D3.API.Material(
this.id,
this.materialType,
this.name,
this.opacity,
this.side,
this.transparent,
this.specular.toApiObject(),
this.lightMapIntensity,
this.aoMapIntensity,
this.color.toApiObject(),
this.emissive.toApiObject(),
this.emissiveIntensity,
this.combine,
this.shininess,
this.reflectivity,
this.refractionRatio,
this.fog,
this.wireframe,
this.wireframeLineWidth,
this.wireframeLineCap,
this.wireframeLineJoin,
this.vertexColors,
this.skinning,
this.morphTargets,
this.morphNormals,
this.lineWidth,
this.lineCap,
this.lineJoin,
this.dashSize,
this.gapWidth,
this.blending,
this.blendSrc,
this.blendDst,
this.blendEquation,
this.depthTest,
this.depthFunc,
this.depthWrite,
this.polygonOffset,
this.polygonOffsetFactor,
this.polygonOffsetUnits,
this.alphaTest,
this.clippingPlanes,
this.clipShadows,
this.visible,
this.overdraw,
this.flatShading,
this.bumpScale,
this.normalScale,
this.displacementScale,
this.displacementBias,
this.roughness,
this.metalness,
this.pointSize,
this.pointSizeAttenuation,
this.spriteRotation,
this.envMapIntensity,
apiAlphaMap,
apiAoMap,
apiBumpMap,
apiDiffuseMap,
apiDisplacementMap,
apiEmissiveMap,
apiEnvironmentMap,
apiLightMap,
apiMetalnessMap,
apiNormalMap,
apiRoughnessMap,
apiSpecularMap,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiMaterial;
};
GameLib.D3.Material.prototype.getTextures = function() {
var textures = [];
if (this.alphaMap) {
textures.push(this.alphaMap);
}
if (this.aoMap) {
textures.push(this.aoMap);
}
if (this.bumpMap) {
textures.push(this.bumpMap);
}
if (this.diffuseMap) {
textures.push(this.diffuseMap);
}
if (this.displacementMap) {
textures.push(this.displacementMap);
}
if (this.emissiveMap) {
textures.push(this.emissiveMap);
}
if (this.environmentMap) {
textures.push(this.environmentMap);
}
if (this.lightMap) {
textures.push(this.lightMap);
}
if (this.metalnessMap) {
textures.push(this.metalnessMap);
}
if (this.normalMap) {
textures.push(this.normalMap);
}
if (this.roughnessMap) {
textures.push(this.roughnessMap);
}
if (this.specularMap) {
textures.push(this.specularMap);
}
return textures;
};
/**
* Creates a GameLib.D3.Material from a material Object
* @param graphics GameLib.D3.Graphics
* @param objectMaterial Object
* @constructor
*/
GameLib.D3.Material.FromObject = function(graphics, objectMaterial) {
var gameLibMaterial = new GameLib.D3.Material(
graphics,
GameLib.D3.API.Material.FromObject(objectMaterial)
);
return gameLibMaterial;
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @constructor
*/
GameLib.D3.Mesh = function (
graphics,
apiMesh
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMesh)) {
apiMesh = {};
}
if (apiMesh instanceof GameLib.D3.Mesh) {
return apiMesh;
}
GameLib.D3.API.Mesh.call(
this,
apiMesh.id,
apiMesh.meshType,
apiMesh.name,
apiMesh.vertices,
apiMesh.faces,
apiMesh.materials,
apiMesh.parentMesh,
apiMesh.parentScene,
apiMesh.skeleton,
apiMesh.skinIndices,
apiMesh.skinWeights,
apiMesh.position,
apiMesh.quaternion,
apiMesh.rotation,
apiMesh.scale,
apiMesh.up,
apiMesh.modelMatrix,
apiMesh.parentEntity,
apiMesh.renderOrder,
apiMesh.isBufferMesh,
apiMesh.useQuaternion,
apiMesh.visible
);
this.faces = this.faces.map(
function(face) {
if (face instanceof GameLib.D3.API.Face) {
return new GameLib.D3.Face(
this.graphics,
face
)
} else {
return face;
}
}.bind(this)
);
this.materials = this.materials.map(
function(material) {
if (material instanceof GameLib.D3.API.Material) {
return new GameLib.D3.Material(
this.graphics,
material
)
} else {
return material;
}
}.bind(this)
);
if (this.skeleton) {
this.skeleton = new GameLib.D3.Skeleton(
this.graphics,
this.skeleton
);
}
this.vertices = this.vertices.map(
function (apiVertex) {
return new GameLib.D3.Vertex(
this.graphics,
apiVertex
);
}.bind(this)
);
this.position = new GameLib.Vector3(
this.graphics,
this.position,
this
);
this.quaternion = new GameLib.Quaternion(
this.graphics,
this.quaternion,
this
);
this.rotation = new GameLib.Vector3(
this.graphics,
this.rotation,
this
);
this.scale = new GameLib.Vector3(
this.graphics,
this.scale,
this
);
this.up = new GameLib.Vector3(
this.graphics,
this.up,
this
);
this.modelMatrix = new GameLib.Matrix4(
this.graphics,
this.modelMatrix,
this
);
this.dimensions = new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(),
this
);
var linkedObjects = {
'parentMesh' : GameLib.D3.Mesh,
'parentScene' : GameLib.D3.Scene,
'materials' : [GameLib.D3.Material],
'skeleton' : GameLib.D3.Skeleton
};
var componentType = GameLib.Component.COMPONENT_MESH;
if (this.meshType === GameLib.D3.Mesh.MESH_TYPE_PLANE) {
componentType = GameLib.Component.COMPONENT_MESH_PLANE
}
if (this.meshType === GameLib.D3.Mesh.MESH_TYPE_BOX) {
componentType = GameLib.Component.COMPONENT_MESH_BOX
}
if (this.meshType === GameLib.D3.Mesh.MESH_TYPE_CYLINDER) {
componentType = GameLib.Component.COMPONENT_MESH_CYLINDER
}
if (this.meshType === GameLib.D3.Mesh.MESH_TYPE_SPHERE) {
componentType = GameLib.Component.COMPONENT_MESH_SPHERE
}
if (this.meshType === GameLib.D3.Mesh.MESH_TYPE_LINE) {
componentType = GameLib.Component.COMPONENT_MESH_LINE
}
if (this.meshType === GameLib.D3.Mesh.MESH_TYPE_TEXT) {
componentType = GameLib.Component.COMPONENT_MESH_TEXT;
linkedObjects.font = GameLib.D3.Font;
}
/**
* Runtime meshes have helpers too
* @type {null}
*/
this.helper = null;
this.updateRotationFromAxisAngle = true;
GameLib.Component.call(
this,
componentType,
linkedObjects
);
};
GameLib.D3.Mesh.prototype = Object.create(GameLib.D3.API.Mesh.prototype);
GameLib.D3.Mesh.prototype.constructor = GameLib.D3.Mesh;
/**
* Mesh Type
* @type {number}
*/
GameLib.D3.Mesh.MESH_TYPE_NORMAL = 0x0;
GameLib.D3.Mesh.MESH_TYPE_SKINNED = 0x1;
GameLib.D3.Mesh.MESH_TYPE_CURVE = 0x2;
GameLib.D3.Mesh.MESH_TYPE_SPHERE = 0x3;
GameLib.D3.Mesh.MESH_TYPE_PLANE = 0x4;
GameLib.D3.Mesh.MESH_TYPE_BOX = 0x5;
GameLib.D3.Mesh.MESH_TYPE_CYLINDER = 0x6;
GameLib.D3.Mesh.MESH_TYPE_TEXT = 0x7;
GameLib.D3.Mesh.MESH_TYPE_LINE = 0x8;
GameLib.D3.Mesh.prototype.lookAt = function(vector) {
this.instance.lookAt(
new THREE.Vector3(
vector.x,
vector.y,
vector.z
)
);
this.rotation.x = this.instance.rotation.x;
this.rotation.y = this.instance.rotation.y;
this.rotation.z = this.instance.rotation.z;
this.quaternion.x = this.instance.quaternion.x;
this.quaternion.y = this.instance.quaternion.y;
this.quaternion.z = this.instance.quaternion.z;
this.quaternion.w = this.instance.quaternion.w;
};
GameLib.D3.Mesh.prototype.createInstanceGeometry = function(instanceGeometry) {
if (instanceGeometry instanceof THREE.Geometry) {
this.computeBoundingBox(instanceGeometry);
if (this.isBufferMesh) {
return new THREE.BufferGeometry().fromGeometry(instanceGeometry);
}
}
/**
* Setup face indexes - first we sort according to the material index, because later we will create
* groups for each vertice group
*/
this.faces.sort(function(a, b){
if (a.materialIndex < b.materialIndex) {
return -1;
}
if (a.materialIndex > b.materialIndex) {
return 1;
}
return 0;
});
/**
* Setup mesh vertices positions
* @type {Float32Array}
*/
var vertices = new Float32Array(
this.faces.reduce(
function(result, face){
result.push(this.vertices[face.v0index].position.x);
result.push(this.vertices[face.v0index].position.y);
result.push(this.vertices[face.v0index].position.z);
result.push(this.vertices[face.v1index].position.x);
result.push(this.vertices[face.v1index].position.y);
result.push(this.vertices[face.v1index].position.z);
result.push(this.vertices[face.v2index].position.x);
result.push(this.vertices[face.v2index].position.y);
result.push(this.vertices[face.v2index].position.z);
return result;
}.bind(this),
[]
)
);
var geometry = null;
if (this.isBufferMesh) {
geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
/**
* Setyp mesh vertices colors
*/
var colors = Float32Array.from(
this.faces.reduce(
function(result, face){
result.push(1,1,1,1,1,1,1,1,1);
// result.push(face.color.r);
// result.push(face.color.g);
// result.push(face.color.b);
// result.push(face.color.r);
// result.push(face.color.g);
// result.push(face.color.b);
// result.push(face.color.r);
// result.push(face.color.g);
// result.push(face.color.b);
return result;
}.bind(this),
[]
)
);
geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3, true));
/**
* Setup face UVs
*/
var uvs = Float32Array.from(
this.faces.reduce(
function(result, face) {
face.uvs[0].map(
function(uv) {
result.push(uv.x);
result.push(uv.y);
}
);
return result;
},
[]
)
);
geometry.addAttribute('uv', new THREE.BufferAttribute(uvs, 2));
/**
* Setup material groups - this means creating a new group for each material index change
* We know faces are sorted according to material index
*/
var groupIndexCounts = this.faces.reduce(
function(result, face) {
var currentGroup = result.pop();
if (currentGroup.index !== face.materialIndex) {
/**
* We have a new group
*/
result.push(currentGroup);
result.push({
index: face.materialIndex,
count: 3
})
} else {
currentGroup.count += 3;
result.push(currentGroup);
}
return result;
},
[
{
index : 0,
count : 0
}
]
);
groupIndexCounts.reduce(
function(start, group) {
geometry.addGroup(start, group.count, group.index);
return start + group.count;
},
0
);
} else {
geometry = new THREE.Geometry();
var standardUvs = [];
/**
* Face data
* @type {Array}
*/
geometry.faces = this.faces.map(
function (face) {
if (face.uvs[0].length > 0) {
standardUvs.push(
face.uvs[0].map(
function(uv) {
return new THREE.Vector2(
uv.x,
uv.y
)
}
)
);
}
var faceInstance = new THREE.Face3(
face.v0index,
face.v1index,
face.v2index
);
if (face.normal) {
faceInstance.normal = new THREE.Vector3(
face.normal.x,
face.normal.y,
face.normal.z
);
}
if (face.color) {
faceInstance.color = new THREE.Color(
face.color.r,
face.color.g,
face.color.b
)
}
faceInstance.materialIndex = face.materialIndex;
return faceInstance;
}
);
/**
* Vertex data
* @type {Array}
*/
geometry.vertices = this.vertices.map(
function (vertex) {
return new THREE.Vector3(
vertex.position.x,
vertex.position.y,
vertex.position.z
)
}
);
geometry.verticesNeedUpdate = true;
/**
* UV data - but only if it exists
*/
if (standardUvs.length > 0) {
geometry.faceVertexUvs = [standardUvs];
}
/**
* Re-compute normals - we don't do this for buffer geometry because it assigns to every vertex normal the face
* normal - essentially disabling 'smooth shading'
*/
geometry.computeFaceNormals();
// geometry.computeBoundingBox();
geometry.computeVertexNormals();
// geometry.verticesNeedUpdate = true;
// geometry.elementsNeedUpdate = true;
// geometry.morphTargetsNeedUpdate = true;
// geometry.uvsNeedUpdate = true;
// geometry.normalsNeedUpdate = true;
// geometry.colorsNeedUpdate = true;
// geometry.tangentsNeedUpdate = true;
}
/**
* Apply skin indices
*/
// this.applyBones(geometry);
this.computeBoundingBox(geometry);
return geometry;
};
/**
* Creates a mesh instance or updates it
*/
GameLib.D3.Mesh.prototype.createInstance = function() {
var geometry = this.createInstanceGeometry();
if (this.skeleton) {
if (this.materials.length === 1) {
this.instance = new THREE.SkinnedMesh(
geometry,
this.materials[0].instance
)
} else {
this.instance = new THREE.SkinnedMesh(
geometry,
this.materials.map(
function(material) {
return material.instance;
}
)
)
}
this.instance.add(this.skeleton.rootBoneInstance);
this.instance.bind(this.skeleton.instance);
} else {
if (this.materials.length === 1) {
this.instance = new THREE.Mesh(
geometry,
this.materials[0].instance
)
} else {
this.instance = new THREE.Mesh(
geometry,
this.materials.map(
function(material) {
return material.instance;
}
)
)
}
}
this.instance.name = this.name;
if (this.parentMesh && this.parentMesh.instance) {
this.parentMesh.add(this.instance, this);
}
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
if (this.useQuaternion) {
this.instance.quaternion.x = this.quaternion.x;
this.instance.quaternion.y = this.quaternion.y;
this.instance.quaternion.z = this.quaternion.z;
this.instance.quaternion.w = this.quaternion.w;
this.instance.quaternion.setFromAxisAngle(
new THREE.Vector3(
this.quaternion.axis.x,
this.quaternion.axis.y,
this.quaternion.axis.z
),
this.quaternion.angle
);
} else {
this.instance.rotation.x = this.rotation.x;
this.instance.rotation.y = this.rotation.y;
this.instance.rotation.z = this.rotation.z;
}
this.instance.scale.x = this.scale.x;
this.instance.scale.y = this.scale.y;
this.instance.scale.z = this.scale.z;
this.instance.up.x = this.up.x;
this.instance.up.y = this.up.y;
this.instance.up.z = this.up.z;
this.instance.renderOrder = this.renderOrder;
this.instance.visible = this.visible;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the mesh instance
*/
GameLib.D3.Mesh.prototype.updateInstance = function(property) {
if (GameLib.Utils.UndefinedOrNull(property)) {
console.warn('unknown mesh property update');
}
if (property === 'isBufferMesh') {
if (( this.isBufferMesh && !(this.instance.geometry instanceof THREE.BufferGeometry)) ||
( !this.isBufferMesh && (this.instance.geometry instanceof THREE.BufferGeometry)))
{
/**
* The buffer geometry needs updating
*/
this.instance.geometry = this.createInstanceGeometry(this.instance.geometry);
}
}
if (
property === 'rotation' ||
property === 'quaternion' ||
property === 'useQuaternion'
) {
this.updateInstanceRotation();
}
if (property === 'parentMesh') {
if (this.parentMesh && this.parentMesh.instance) {
if (this.instance.parent !== this.parentMesh.instance) {
this.instance.parent = this.parentMesh.instance;
}
}
}
if (property === 'scale') {
this.updateInstanceScale();
}
if (property === 'position') {
this.updateInstancePosition();
}
if (property === 'up') {
this.instance.up.x = this.up.x;
this.instance.up.y = this.up.y;
this.instance.up.z = this.up.z;
}
if (property === 'name') {
this.instance.name = this.name;
}
if (property === 'materials') {
if (this.materials.length === 1 && this.materials[0].instance) {
this.instance.material = this.materials[0].instance;
}
}
if (property === 'renderOrder') {
this.instance.renderOrder = this.renderOrder;
}
if (property === 'visible') {
this.instance.visible = this.visible;
}
if (this.helper) {
this.removeHelper();
this.createHelper();
}
};
/**
* Apply geometry data to our game-lib object from the geometry instance (reverse of applyVertexData)
* @param geometryInstance
*/
GameLib.D3.Mesh.prototype.updateVerticesFromGeometryInstance = function(geometryInstance) {
/**
* Setup vertices
*/
this.vertices = [];
this.faces = [];
if (geometryInstance instanceof THREE.BufferGeometry) {
var vertices = geometryInstance.getAttribute('position').array;
var uvs = geometryInstance.getAttribute('uv').array;
geometryInstance.groups.map(function(group){
var materialIndex = group.materialIndex;
var start = group.start;
var count = group.count;
var faceIndexes = [];
var indexedUvs = [];
for (var i = start; i < count; i ++) {
var vertex = new GameLib.D3.Vertex(
this.graphics,
new GameLib.D3.API.Vertex(
new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(
vertices[i*3],
vertices[i*3 + 1],
vertices[i*3 + 2]
)
)
)
);
var uv = new GameLib.Vector2(
this.graphics,
new GameLib.API.Vector2(
uvs[i*2],
uvs[i*2 + 1]
)
);
indexedUvs.push(uv);
var vertexIndex = this.vertices.reduce(
function(result, indexedVertex, currentIndex){
if (indexedVertex.position.equals(vertex.position)) {
result = currentIndex;
}
return result;
},
-1
);
var faceIndex = vertexIndex;
if (vertexIndex === -1) {
this.vertices.push(vertex);
faceIndex = this.vertices.length - 1;
}
faceIndexes.push(faceIndex);
if (faceIndexes.length === 3) {
this.faces.push(
new GameLib.D3.Face(
this.graphics,
new GameLib.D3.API.Face(
null,
null,
faceIndexes[0],
faceIndexes[1],
faceIndexes[2],
materialIndex,
[[indexedUvs[0], indexedUvs[1], indexedUvs[2]]]
)
)
);
indexedUvs = [];
faceIndexes = [];
}
}
}.bind(this));
console.log('todo : update vertices from buffer geometry');
} else {
var processed = 0;
geometryInstance.faces.map(function(face, faceIndex){
processed++;
if (processed % 100 === 0) {
console.log('processed ' + processed + ' faces');
}
this.faces.push(
new GameLib.D3.Face(
this.graphics,
new GameLib.D3.API.Face(
null,
null,
face.a,
face.b,
face.c,
face.materialIndex,
[[
new GameLib.API.Vector2(
geometryInstance.faceVertexUvs[0][faceIndex][0].x,
geometryInstance.faceVertexUvs[0][faceIndex][0].y
),
new GameLib.API.Vector2(
geometryInstance.faceVertexUvs[0][faceIndex][1].x,
geometryInstance.faceVertexUvs[0][faceIndex][1].y
),
new GameLib.API.Vector2(
geometryInstance.faceVertexUvs[0][faceIndex][2].x,
geometryInstance.faceVertexUvs[0][faceIndex][2].y
)
]],
new GameLib.Color(
this.graphics,
new GameLib.API.Color(
face.color.r,
face.color.g,
face.color.b
)
),
face.vertexColors.map(function(vertexColor){
return new GameLib.Color(
this.graphics,
new GameLib.API.Color(
vertexColor.r,
vertexColor.g,
vertexColor.b
)
)
}.bind(this)),
face.vertexNormals.map(function(vertexNormal){
return new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(
vertexNormal.x,
vertexNormal.y,
vertexNormal.z
)
)
}.bind(this)),
new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(
face.normal.x,
face.normal.y,
face.normal.z
)
)
)
)
)
}.bind(this));
processed = 0;
geometryInstance.vertices.map(function(vertex){
processed++;
if (processed % 100 === 0) {
console.log('processed ' + processed + ' vertices');
}
this.vertices.push(
new GameLib.D3.Vertex(
this.graphics,
new GameLib.D3.API.Vertex(
new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(
vertex.x,
vertex.y,
vertex.z
)
)
)
)
)
}.bind(this));
}
};
GameLib.D3.Mesh.prototype.applyBones = function(geometry) {
/**
* Setup Bone Indexes
*/
this.skinIndices.map(
function(skinIndex) {
geometry.skinIndices.push(
new THREE.Vector4(
skinIndex.x,
skinIndex.y,
skinIndex.z,
skinIndex.w
)
);
}
);
/**
* Setup Bone Weights
*/
this.skinWeights.map(
function(skinWeight) {
geometry.skinWeights.push(
new THREE.Vector4(
skinWeight.x,
skinWeight.y,
skinWeight.z,
skinWeight.w
)
);
}
);
};
/**
* Adds a child instance to this instance
* @param childInstance
* @param child
*/
GameLib.D3.Mesh.prototype.addChild = function(childInstance, child) {
if (!this.instance) {
throw new Error('mesh instance not loaded yet : ' + this.name);
}
if (GameLib.Utils.UndefinedOrNull(childInstance)) {
throw new Error('no child mesh instance');
}
if (GameLib.Utils.UndefinedOrNull(child)) {
throw new Error('no child mesh');
}
this.instance.add(childInstance);
childInstance.parent = this.instance;
child.parentMesh = this;
};
/**
* Sets a parent for this mesh
* @param parentMesh
*/
GameLib.D3.Mesh.prototype.setParentMesh = function(parentMesh) {
/**
* Are we removing this child from the parent?
*/
if (GameLib.Utils.UndefinedOrNull(parentMesh)) {
if (this.instance && this.instance.parent && this.parentScene.instance) {
/**
* Update the parent matrix world
*/
this.instance.parent.updateMatrixWorld();
/**
* Copy the child world position into a temporary vector
* @type {THREE.Vector3}
*/
var vector = new THREE.Vector3();
vector.setFromMatrixPosition(this.instance.matrixWorld);
/**
* Detach child from parent within this scene
*/
THREE.SceneUtils.detach(
this.instance,
this.instance.parent,
this.parentScene.instance
);
/**
* We remember from now on that we have no parent mesh
* @type {null}
*/
this.parentMesh = null;
/**
* We store the world position back to the child
*/
this.position.x = vector.x;
this.position.y = vector.y;
this.position.z = vector.z;
/**
* Update the instance position
*/
this.updateInstancePosition();
/**
* Don't touch this instance parent - since it is now probably a scene object
*/
/**
* TODO: do we apply rotation somehow?
*/
} else {
throw new Error('Not enough information to detach')
}
} else {
if (!this.instance) {
throw new Error('No valid instance at time of adding to parent for mesh ' + this.name);
}
if (!(parentMesh instanceof GameLib.D3.Mesh)) {
throw new Error('Not a valid parent mesh');
}
this.parentMesh = parentMesh;
/**
* Add this as a child to the parent
*/
this.parentMesh.addChild(this.instance, this);
}
};
// GameLib.D3.Mesh.prototype.getBoundingBox = function() {
//
// this.instance.geometry.computeBoundingBox();
//
// return new GameLib.Vector3(
// this.graphics,
// new GameLib.API.Vector3(
// this.instance.geometry.boundingBox.max.x - this.instance.geometry.boundingBox.min.x,
// this.instance.geometry.boundingBox.max.y - this.instance.geometry.boundingBox.min.y,
// this.instance.geometry.boundingBox.max.z - this.instance.geometry.boundingBox.min.z
// )
// );
//
// };
/**
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.prototype.toApiObject = function() {
var apiSkeleton = null;
if (this.skeleton) {
apiSkeleton = this.skeleton.id;
}
var apiMaterials = null;
if (this.materials) {
apiMaterials = this.materials.map(
function(material) {
return material.id;
}
)
}
var apiFaces = this.faces.map(
function(face){
return face.toApiObject();
}
);
var apiMesh = new GameLib.D3.API.Mesh(
this.id,
this.meshType,
this.name,
this.vertices.map(
function (vertex) {
return vertex.toApiObject();
}
),
apiFaces,
apiMaterials,
GameLib.Utils.IdOrNull(this.parentMesh),
GameLib.Utils.IdOrNull(this.parentScene),
apiSkeleton,
this.skinIndices,
this.skinWeights,
this.position.toApiObject(),
this.quaternion.toApiObject(),
this.rotation.toApiObject(),
this.scale.toApiObject(),
this.up.toApiObject(),
this.modelMatrix.toApiObject(),
GameLib.Utils.IdOrNull(this.parentEntity),
this.renderOrder,
this.isBufferMesh,
this.useQuaternion,
this.visible
);
return apiMesh;
};
/**
* Converts a standard object mesh to a GameLib.D3.Mesh
* @param graphics GameLib.D3.Graphics
* @param objectMesh {Object}
* @constructor
*/
GameLib.D3.Mesh.FromObject = function(graphics, objectMesh) {
var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh);
return new GameLib.D3.Mesh(
graphics,
apiMesh
);
};
/**
* Centers the mesh around origin
*/
GameLib.D3.Mesh.prototype.centerAroundOrigin = function() {
var position = this.instance.geometry.center();
this.instance.position.set(0,0,0);
this.instance.updateMatrix();
for (var v = 0; v < this.instance.geometry.vertices.length; v++) {
this.vertices[v].position.x = this.instance.geometry.vertices[v].x;
this.vertices[v].position.y = this.instance.geometry.vertices[v].y;
this.vertices[v].position.z = this.instance.geometry.vertices[v].z;
}
this.position.x = -position.x;
this.position.y = -position.y;
this.position.z = -position.z;
this.updateInstancePosition();
return position;
};
GameLib.D3.Mesh.prototype.applyAxisAngleToPosition = function(axis, angle) {
if (GameLib.Utils.UndefinedOrNull(axis)) {
axis = this.quaternion.axis;
}
if (GameLib.Utils.UndefinedOrNull(angle)) {
angle = this.quaternion.angle;
}
this.position.applyAxisAngle(axis, angle);
this.updateInstancePosition();
};
GameLib.D3.Mesh.prototype.applyAxisAngleToUvs = function(axis, angle) {
if (GameLib.Utils.UndefinedOrNull(axis)) {
axis = this.quaternion.axis;
}
if (GameLib.Utils.UndefinedOrNull(angle)) {
angle = this.quaternion.angle;
}
// this.instance.geometry.faceVertexUvs[0].map(
// function(uvs) {
// uvs.map(function(uv) {
//
// var x = uv.x;
//
// uv.x = uv.y;
// uv.y = x;
//
// //var v = new THREE.Vector3(uv.x, uv.y, 0);
// //v.applyAxisAngle(axis, angle);
// //uv.x = v.x;
// //uv.y = v.u;
// });
// }
// );
this.instance.geometry.uvsNeedUpdate = true;
//
// this.faces.map(
// function(face) {
// face.uvs.map(function(uvs){
// uvs.map(
// function(uv) {
// var v = new GameLib.Vector3(this.graphics, new GameLib.API.Vector3(uv.x, uv.y, 0));
// v.applyAxisAngle(axis, angle);
// uv.x = v.x;
// uv.y = v.y;
// }
// )
// });
// }
// )
};
GameLib.D3.Mesh.prototype.translate = function(vector3) {
this.position.x += vector3.x;
this.position.y += vector3.y;
this.position.z += vector3.z;
this.updateInstancePosition();
};
GameLib.D3.Mesh.prototype.getDistanceFromCenter = function() {
var position = this.instance.geometry.center();
return new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(
position.x,
position.y,
position.z
)
)
};
/**
* Applies position, rotation and scale to the object vertice data, resets scale, rotation and sets position to origin.
*/
GameLib.D3.Mesh.prototype.applyPositionRotationScale = function() {
this.instance.updateMatrix();
this.instance.geometry.applyMatrix(this.instance.matrix);
/**
* Reset position
* @type {number}
*/
this.position.x = 0;
this.position.y = 0;
this.position.z = 0;
this.updateInstancePosition();
/**
* Reset scale
* @type {number}
*/
this.scale.x = 1;
this.scale.y = 1;
this.scale.z = 1;
this.instance.scale.set(1,1,1);
/**
* Reset rotation
* @type {number}
*/
this.quaternion.x = 0;
this.quaternion.y = 0;
this.quaternion.z = 0;
this.quaternion.w = 1;
this.quaternion.axis.x = 0;
this.quaternion.axis.y = 0;
this.quaternion.axis.z = 0;
this.quaternion.angle = 0;
this.rotation.x = 0;
this.rotation.y = 0;
this.rotation.z = 0;
this.updateInstanceRotation();
/**
* Update our instance matrix
*/
this.instance.updateMatrix();
/**
* Let this reflect back to our vertices
*/
this.updateVerticesFromGeometryInstance(this.instance.geometry);
};
GameLib.D3.Mesh.prototype.updateInstanceRotationFromAxisAngle = function(axis, angle) {
if (GameLib.Utils.UndefinedOrNull(axis)) {
axis = this.quaternion.axis;
}
if (GameLib.Utils.UndefinedOrNull(angle)) {
angle = this.quaternion.angle;
}
this.quaternion.axis.instance.x = axis.x;
this.quaternion.axis.instance.y = axis.y;
this.quaternion.axis.instance.z = axis.z;
this.quaternion.instance.setFromAxisAngle(this.quaternion.axis.instance, angle);
this.instance.quaternion.copy(this.quaternion.instance);
this.quaternion.x = this.quaternion.instance.x;
this.quaternion.y = this.quaternion.instance.y;
this.quaternion.z = this.quaternion.instance.z;
this.quaternion.w = this.quaternion.instance.w;
};
GameLib.D3.Mesh.prototype.updateInstanceRotation = function() {
if (this.useQuaternion) {
this.updateInstanceRotationFromAxisAngle();
} else {
this.rotation.instance.set(
this.rotation.x,
this.rotation.y,
this.rotation.z
);
this.instance.rotation.set(
this.rotation.x,
this.rotation.y,
this.rotation.z
);
}
if (this.helper) {
this.helper.updateInstance();
}
};
GameLib.D3.Mesh.prototype.updateInstancePosition = function() {
this.position.instance.set(
this.position.x,
this.position.y,
this.position.z
);
this.instance.position.copy(this.position.instance);
if (this.helper) {
this.removeHelper();
this.createHelper();
}
};
GameLib.D3.Mesh.prototype.updateInstanceScale = function() {
this.scale.instance.set(
this.scale.x,
this.scale.y,
this.scale.z
);
this.instance.scale.copy(this.scale.instance);
if (this.helper) {
this.removeHelper();
this.createHelper();
}
};
/**
* Gets all children components of this Mesh (all linked objects only - no object references i.e. string ids)
* @returns {Array}
*/
GameLib.D3.Mesh.prototype.getChildrenComponents = function() {
var components = [];
this.materials.map(
function (material) {
if (material instanceof GameLib.D3.Material) {
GameLib.Utils.PushUnique(components, material);
for (var property in material.linkedObjects) {
if (
material.linkedObjects.hasOwnProperty(property) &&
material.hasOwnProperty(property) &&
material[property] &&
typeof material[property] !== 'string' &&
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] &&
typeof material[property][tProperty] !== 'string' &&
tProperty !== 'parentEntity'
) {
if (material[property][tProperty] instanceof Array) {
material[property][tProperty].map(
function(object) {
GameLib.Utils.PushUnique(components, object);
}
)
} else {
GameLib.Utils.PushUnique(components, material[property][tProperty]);
}
}
}
}
}
}
}.bind(this)
);
/**
* Push RigidBodies
*/
var rigidBodies = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RigidBody);
rigidBodies.map(
function(rigidBody) {
if (rigidBody.parentMesh === this) {
GameLib.Utils.PushUnique(components, rigidBody);
}
}.bind(this)
);
/**
* Push Shapes
*/
var shapes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Shape);
shapes.map(
function(shape) {
if (shape.parentMesh === this) {
GameLib.Utils.PushUnique(components, shape);
}
}.bind(this)
);
return components;
};
/**
* Convenience function for creating a helper for this Mesh - should be called from Systems only
*/
GameLib.D3.Mesh.prototype.createHelper = function() {
if (GameLib.Utils.UndefinedOrNull(this.parentScene) ||
GameLib.Utils.UndefinedOrNull(this.parentScene.instance)) {
console.warn('this mesh has no parent scene - cannot create helper');
return;
}
if (this.helper) {
this.removeHelper();
}
this.helper = new GameLib.D3.Helper(
this.graphics,
null,
this.name + ' Helper',
this,
GameLib.D3.Helper.HELPER_TYPE_EDGES
);
this.helper.updateInstance();
/**
* Backup the polygonOffset value, then set it to 'true' - helps for clear nice outlines
*/
this.polygonOffset = this.instance.material.polygonOffset;
this.instance.material.polygonOffset = true;
this.parentScene.instance.add(this.helper.instance);
};
GameLib.D3.Mesh.prototype.addMaterial = function(material) {
if (this.materials.length === 1) {
this.instance.material = material.instance;
} else {
this.instance.material = this.materials.map(
function(material) {
return material.instance;
}
);
}
};
/**
* Convenience function for removing a helper for this Mesh - should be called from Systems only
*/
GameLib.D3.Mesh.prototype.removeHelper = function() {
if (GameLib.Utils.UndefinedOrNull(this.parentScene) ||
GameLib.Utils.UndefinedOrNull(this.parentScene.instance)) {
console.warn('this mesh has no parent scene - cannot remove helper');
return;
}
if (this.helper && this.helper.instance) {
this.parentScene.instance.remove(this.helper.instance);
delete this.helper.instance;
}
this.instance.material.polygonOffset = this.polygonOffset;
this.helper = null;
};
GameLib.D3.Mesh.prototype.computeBoundingBox = function(geometry) {
if (GameLib.Utils.UndefinedOrNull(geometry)) {
if (this.instance && this.instance.geometry) {
geometry = this.instance.geometry;
} else {
console.log('no instance geometry to compute bounding box');
}
}
geometry.computeBoundingBox();
this.dimensions.x = geometry.boundingBox.getSize().x;
this.dimensions.y = geometry.boundingBox.getSize().y;
this.dimensions.z = geometry.boundingBox.getSize().z;
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @param width
* @param height
* @param depth
* @constructor
*/
GameLib.D3.Mesh.Box = function (
graphics,
apiMesh,
width,
height,
depth
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMesh)) {
apiMesh = {};
}
if (apiMesh instanceof GameLib.D3.Mesh.Box) {
return apiMesh;
}
apiMesh.meshType = GameLib.D3.Mesh.MESH_TYPE_BOX;
if (GameLib.Utils.UndefinedOrNull(width)) {
width = 1;
}
this.width = width;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 1;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(depth)) {
depth = 1;
}
this.depth = depth;
GameLib.D3.Mesh.call(
this,
this.graphics,
apiMesh
);
};
GameLib.D3.Mesh.Box.prototype = Object.create(GameLib.D3.Mesh.prototype);
GameLib.D3.Mesh.Box.prototype.constructor = GameLib.D3.Mesh.Box;
GameLib.D3.Mesh.Box.prototype.createInstance = function() {
var geometry = null;
if (this.vertices.length === 0) {
geometry = new THREE.BoxGeometry(
this.width,
this.height,
this.depth
);
this.updateVerticesFromGeometryInstance(geometry);
}
GameLib.D3.Mesh.prototype.createInstance.call(this);
this.instance.userData.width = this.width;
this.instance.userData.height = this.height;
this.instance.userData.depth = this.depth;
};
GameLib.D3.Mesh.Box.prototype.updateInstance = function(property) {
if (
this.instance.userData.width !== this.width ||
this.instance.userData.height !== this.height ||
this.instance.userData.depth !== this.depth
) {
this.instance.userData.width = this.width;
this.instance.userData.height = this.height;
this.instance.userData.depth = this.depth;
var geometry = new THREE.BoxGeometry(
this.width,
this.height,
this.depth
);
this.updateVerticesFromGeometryInstance(geometry);
geometry = this.createInstanceGeometry();
this.instance.geometry = geometry;
}
GameLib.D3.Mesh.prototype.updateInstance.call(this, property);
};
/**
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.Box.prototype.toApiObject = function() {
var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this);
apiMesh.width = this.width;
apiMesh.height = this.height;
apiMesh.depth = this.depth;
return apiMesh;
};
/**
* Converts a standard object mesh to a GameLib.D3.Mesh
* @param graphics GameLib.D3.Graphics
* @param objectMesh {Object}
* @constructor
*/
GameLib.D3.Mesh.Box.FromObject = function(graphics, objectMesh) {
var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh);
return new GameLib.D3.Mesh.Box(
graphics,
apiMesh,
objectMesh.width,
objectMesh.height,
objectMesh.depth
);
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @constructor
*/
GameLib.D3.Mesh.Curve = function (
graphics,
apiMesh
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
GameLib.D3.Mesh.call(
this,
this.graphics,
apiMesh
);
};
GameLib.D3.Mesh.Curve.prototype = Object.create(GameLib.D3.Mesh.prototype);
GameLib.D3.Mesh.Curve.prototype.constructor = GameLib.D3.Mesh.Curve;
GameLib.D3.Mesh.Curve.prototype.createInstance = function() {
var geometry = new THREE.Geometry();
/**
* Setup vertices
*/
this.applyVertexDataToInstance(geometry);
var instance = new THREE.Points(geometry);
this.createInstanceDefaults(instance);
return instance;
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @param radiusTop
* @param radiusBottom
* @param height
* @param radiusSegments
* @param heightSegments
* @param openEnded
* @param thetaStart
* @param thetaLength
* @constructor
*/
GameLib.D3.Mesh.Cylinder = function (
graphics,
apiMesh,
radiusTop,
radiusBottom,
height,
radiusSegments,
heightSegments,
openEnded,
thetaStart,
thetaLength
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMesh)) {
apiMesh = {};
}
if (apiMesh instanceof GameLib.D3.Mesh.Box) {
return apiMesh;
}
apiMesh.meshType = GameLib.D3.Mesh.MESH_TYPE_CYLINDER;
if (GameLib.Utils.UndefinedOrNull(radiusTop)) {
radiusTop = 1;
}
this.radiusTop = radiusTop;
if (GameLib.Utils.UndefinedOrNull(radiusBottom)) {
radiusBottom = 1;
}
this.radiusBottom = radiusBottom;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 5;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(radiusSegments)) {
radiusSegments = 10;
}
this.radiusSegments = radiusSegments;
if (GameLib.Utils.UndefinedOrNull(heightSegments)) {
heightSegments = 10;
}
this.heightSegments = heightSegments;
if (GameLib.Utils.UndefinedOrNull(openEnded)) {
openEnded = false;
}
this.openEnded = openEnded;
if (GameLib.Utils.UndefinedOrNull(thetaStart)) {
thetaStart = 0;
}
this.thetaStart = thetaStart;
if (GameLib.Utils.UndefinedOrNull(thetaLength)) {
thetaLength = Math.PI * 2;
}
this.thetaLength = thetaLength;
GameLib.D3.Mesh.call(
this,
this.graphics,
apiMesh
);
};
GameLib.D3.Mesh.Cylinder.prototype = Object.create(GameLib.D3.Mesh.prototype);
GameLib.D3.Mesh.Cylinder.prototype.constructor = GameLib.D3.Mesh.Cylinder;
GameLib.D3.Mesh.Cylinder.prototype.createInstance = function() {
var geometry = null;
if (this.vertices.length === 0) {
geometry = new THREE.CylinderGeometry(
this.radiusTop,
this.radiusBottom,
this.height,
this.radiusSegments,
this.heightSegments,
this.openEnded,
this.thetaStart,
this.thetaLength
);
this.updateVerticesFromGeometryInstance(geometry);
}
GameLib.D3.Mesh.prototype.createInstance.call(this);
this.instance.userData.radiusTop = this.radiusTop;
this.instance.userData.radiusBottom = this.radiusBottom;
this.instance.userData.height = this.height;
this.instance.userData.radiusSegments = this.radiusSegments;
this.instance.userData.heightSegments = this.heightSegments;
this.instance.userData.openEnded = this.openEnded;
this.instance.userData.thetaStart = this.thetaStart;
this.instance.userData.thetaLength = this.thetaLength;
};
GameLib.D3.Mesh.Cylinder.prototype.updateInstance = function(property) {
if (
this.instance.userData.radiusTop !== this.radiusTop ||
this.instance.userData.radiusBottom !== this.radiusBottom ||
this.instance.userData.height !== this.height ||
this.instance.userData.radiusSegments !== this.radiusSegments ||
this.instance.userData.heightSegments !== this.heightSegments ||
this.instance.userData.openEnded !== this.openEnded ||
this.instance.userData.thetaStart !== this.thetaStart ||
this.instance.userData.thetaLength !== this.thetaLength
) {
this.instance.userData.radiusTop = this.radiusTop;
this.instance.userData.radiusBottom = this.radiusBottom;
this.instance.userData.height = this.height;
this.instance.userData.radiusSegments = this.radiusSegments;
this.instance.userData.heightSegments = this.heightSegments;
this.instance.userData.openEnded = this.openEnded;
this.instance.userData.thetaStart = this.thetaStart;
this.instance.userData.thetaLength = this.thetaLength;
var geometry = new THREE.CylinderGeometry(
this.radiusTop,
this.radiusBottom,
this.height,
this.radiusSegments,
this.heightSegments,
this.openEnded,
this.thetaStart,
this.thetaLength
);
this.updateVerticesFromGeometryInstance(geometry);
geometry = this.createInstanceGeometry();
this.instance.geometry = geometry;
}
GameLib.D3.Mesh.prototype.updateInstance.call(this, property);
};
/**
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.Cylinder.prototype.toApiObject = function() {
var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this);
apiMesh.radiusTop = this.radiusTop;
apiMesh.radiusBottom = this.radiusBottom;
apiMesh.height = this.height;
apiMesh.radiusSegments = this.radiusSegments;
apiMesh.heightSegments = this.heightSegments;
apiMesh.openEnded = this.openEnded;
apiMesh.thetaStart = this.thetaStart;
apiMesh.thetaLength = this.thetaLength;
return apiMesh;
};
/**
* Converts a standard object mesh to a GameLib.D3.Mesh
* @param graphics GameLib.D3.Graphics
* @param objectMesh {Object}
* @constructor
*/
GameLib.D3.Mesh.Cylinder.FromObject = function(graphics, objectMesh) {
var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh);
return new GameLib.D3.Mesh.Cylinder(
graphics,
apiMesh,
objectMesh.radiusTop,
objectMesh.radiusBottom,
objectMesh.height,
objectMesh.radiusSegments,
objectMesh.heightSegments,
objectMesh.openEnded,
objectMesh.thetaStart,
objectMesh.thetaLength
);
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @param lineWidth
* @constructor
*/
GameLib.D3.Mesh.Line = function (
graphics,
apiMesh,
lineWidth
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMesh)) {
apiMesh = {};
}
if (apiMesh instanceof GameLib.D3.Mesh.Line) {
return apiMesh;
}
apiMesh.meshType = GameLib.D3.Mesh.MESH_TYPE_LINE;
if (GameLib.Utils.UndefinedOrNull(lineWidth)) {
lineWidth = 1;
}
this.lineWidth = lineWidth;
GameLib.D3.Mesh.call(
this,
this.graphics,
apiMesh
);
};
GameLib.D3.Mesh.Line.prototype = Object.create(GameLib.D3.Mesh.prototype);
GameLib.D3.Mesh.Line.prototype.constructor = GameLib.D3.Mesh.Line;
GameLib.D3.Mesh.Line.prototype.createInstance = function() {
var geometry = new THREE.Geometry();
geometry.vertices.push(
this.vertices.map(
function(vertex){
return vertex.instance;
}
)
);
this.instance = new THREE.Line(geometry);
GameLib.D3.Mesh.prototype.createInstance.call(this);
this.instance.userData.lineWidth = this.lineWidth;
};
GameLib.D3.Mesh.Line.prototype.updateInstance = function(property) {
this.instance.linewidth = this.lineWidth;
GameLib.D3.Mesh.prototype.updateInstance.call(this, property);
};
/**
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.Line.prototype.toApiObject = function() {
var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this);
apiMesh.lineWidth = this.lineWidth;
return apiMesh;
};
/**
* Converts a standard object mesh to a GameLib.D3.Mesh
* @param graphics GameLib.D3.Graphics
* @param objectMesh {Object}
* @constructor
*/
GameLib.D3.Mesh.Line.FromObject = function(graphics, objectMesh) {
var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh);
return new GameLib.D3.Mesh.Line(
graphics,
apiMesh,
objectMesh.lineWidth
);
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @param width
* @param height
* @param widthSegments
* @param heightSegments
* @param heightMapScale
* @param isHeightMap
* @param isClippingPlane
* @param distanceFromOrigin
* @constructor
*/
GameLib.D3.Mesh.Plane = function (
graphics,
apiMesh,
width,
height,
widthSegments,
heightSegments,
heightMapScale,
isHeightMap,
isClippingPlane,
distanceFromOrigin
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMesh)) {
apiMesh = {};
}
if (apiMesh instanceof GameLib.D3.Mesh.Box) {
return apiMesh;
}
apiMesh.meshType = GameLib.D3.Mesh.MESH_TYPE_PLANE;
if (GameLib.Utils.UndefinedOrNull(width)) {
width = 1;
}
this.width = width;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 1;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(widthSegments)) {
widthSegments = 1;
}
this.widthSegments = widthSegments;
if (GameLib.Utils.UndefinedOrNull(heightSegments)) {
heightSegments = 1
}
this.heightSegments = heightSegments;
if (GameLib.Utils.UndefinedOrNull(heightMapScale)) {
heightMapScale = 1;
}
this.heightMapScale = heightMapScale;
if (GameLib.Utils.UndefinedOrNull(isHeightMap)) {
isHeightMap = false;
}
this.isHeightMap = isHeightMap;
if (GameLib.Utils.UndefinedOrNull(isClippingPlane)) {
isClippingPlane = false;
}
this.isClippingPlane = isClippingPlane;
if (GameLib.Utils.UndefinedOrNull(distanceFromOrigin)) {
distanceFromOrigin = 0;
}
this.distanceFromOrigin = distanceFromOrigin;
GameLib.D3.Mesh.call(
this,
this.graphics,
apiMesh
);
};
GameLib.D3.Mesh.Plane.prototype = Object.create(GameLib.D3.Mesh.prototype);
GameLib.D3.Mesh.Plane.prototype.constructor = GameLib.D3.Mesh.Plane;
GameLib.D3.Mesh.Plane.prototype.createInstance = function() {
var geometry = null;
/**
* If this geometry is not coming from the database, apply the vertex data from the instance to our runtime object
*/
if (this.vertices.length === 0) {
geometry = new THREE.PlaneGeometry(
this.width,
this.height,
this.widthSegments,
this.heightSegments
);
this.updateVerticesFromGeometryInstance(geometry);
/**
* If this is a heightmap - first generate the z-coordinates
*/
if (this.isHeightMap) {
this.generateHeightMapFromBumpMap();
}
}
/**
* Now construct the mesh instance
*/
GameLib.D3.Mesh.prototype.createInstance.call(this);
/**
* Apply some plane specific data to the instance
*/
this.instance.userData.width = this.width;
this.instance.userData.height = this.height;
this.instance.userData.widthSegments = this.widthSegments;
this.instance.userData.heightSegments = this.heightSegments;
this.instance.userData.heightMapScale = this.heightMapScale;
this.instance.userData.isHeightMap = this.isHeightMap;
this.instance.userData.isClippingPlane = this.isClippingPlane;
this.instance.userData.distanceFromOrigin = this.distanceFromOrigin;
if (this.isClippingPlane) {
this.instance.clipping = new THREE.Plane(
geometry.faces[0].normal,
this.distanceFromOrigin
);
}
};
/**
*
*/
GameLib.D3.Mesh.Plane.prototype.updateInstance = function(property) {
var geometry = null;
if (
this.instance.userData.width !== this.width ||
this.instance.userData.height !== this.height ||
this.instance.userData.widthSegments !== this.widthSegments ||
this.instance.userData.heightSegments !== this.heightSegments ||
this.instance.userData.isHeightMap !== this.isHeightMap ||
this.instance.userData.heightMapScale !== this.heightMapScale ||
this.instance.userData.isClippingPlane !== this.isClippingPlane ||
this.instance.userData.distanceFromOrigin !== this.distanceFromOrigin
) {
this.instance.userData.width = this.width;
this.instance.userData.height = this.height;
this.instance.userData.widthSegments = this.widthSegments;
this.instance.userData.heightSegments = this.heightSegments;
this.instance.userData.isHeightMap = this.isHeightMap;
this.instance.userData.heightMapScale = this.heightMapScale;
this.instance.userData.isClippingPlane = this.isClippingPlane;
this.instance.userData.distanceFromOrigin = this.distanceFromOrigin;
geometry = new THREE.PlaneGeometry(
this.width,
this.height,
this.widthSegments,
this.heightSegments
);
this.updateVerticesFromGeometryInstance(geometry);
if (this.isHeightMap) {
this.generateHeightMapFromBumpMap();
}
geometry = this.createInstanceGeometry();
this.instance.geometry = geometry;
if (this.isClippingPlane) {
this.instance.clipping = new THREE.Plane(
geometry.faces[0].normal,
this.distanceFromOrigin
)
}
}
GameLib.D3.Mesh.prototype.updateInstance.call(this, property);
};
/**
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.Plane.prototype.toApiObject = function() {
var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this);
apiMesh.width = this.width;
apiMesh.height = this.height;
apiMesh.widthSegments = this.widthSegments;
apiMesh.heightSegments = this.heightSegments;
apiMesh.heightMapScale = this.heightMapScale;
apiMesh.isHeightMap = this.isHeightMap;
apiMesh.isClippingPlane = this.isClippingPlane;
apiMesh.distanceFromOrigin = this.distanceFromOrigin;
return apiMesh;
};
/**
* TODO fix all this weird loading shit
* Converts a standard object mesh to a GameLib.D3.Mesh
* @param graphics GameLib.D3.Graphics
* @param objectMesh {Object}
* @constructor
*/
GameLib.D3.Mesh.Plane.FromObject = function(graphics, objectMesh) {
var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh);
return new GameLib.D3.Mesh.Plane(
graphics,
apiMesh,
objectMesh.width,
objectMesh.height,
objectMesh.widthSegments,
objectMesh.heightSegments,
objectMesh.heightMapScale,
objectMesh.isHeightMap,
objectMesh.isClippingPlane,
objectMesh.distanceFromOrigin
);
};
GameLib.D3.Mesh.Plane.prototype.getHeightData = function() {
var i;
var img = this.materials.reduce(
function(result, material) {
if (
material.bumpMap &&
material.bumpMap.image &&
material.bumpMap.image.instance
) {
result = material.bumpMap.image.instance;
}
return result;
},
null
);
if (!img) {
throw new Error('bumpmap image not found');
}
var canvas = document.createElement( 'canvas' );
canvas.width = this.widthSegments + 1;//img.width;
canvas.height = this.heightSegments + 1;//img.height;
var context = canvas.getContext( '2d' );
var size = (this.widthSegments + 1) * (this.heightSegments + 1);
var data = new Float32Array( size );
context.drawImage(img,0,0, canvas.width, canvas.height);
for (i = 0; i < size; i ++ ) {
data[i] = 0
}
var imgd = context.getImageData(0, 0, (this.widthSegments + 1), (this.heightSegments + 1));
var pix = imgd.data;
var j=0;
for (i = 0; i<pix.length; i +=4) {
var all = pix[i]+pix[i+1]+pix[i+2];
data[j++] = all/(12*this.heightMapScale);
}
// data = GameLib.Utils.InterpolateArray(data, (this.widthSegments + 1) * (this.heightSegments + 1));
return data;
};
/**
*
* @returns {THREE.PlaneGeometry}
*/
GameLib.D3.Mesh.Plane.prototype.generateHeightMapFromBumpMap = function() {
var data = this.getHeightData();
this.vertices.map(
function(vertex, index) {
vertex.position.z = data[index];
}
);
// var geometry = this.createInstanceGeometry();
//
// this.instance.geometry = geometry;
//
// var vertices = this.instance.geometry.attributes.position.array;
//
// for ( var i = 0; i < vertices.length; i += 3 ) {
// vertices[i+2] = data[i];
// }
//
// this.instance.geometry.attributes.position.needsUpdate = true;
//this.updateVerticesFromGeometryInstance(this.instance.geometry);
// this.updateInstance();
};
GameLib.D3.Mesh.Plane.prototype.createPhysicsObjects = function() {
GameLib.Event.Emit(
GameLib.Event.GET_PHYSICS_IMPLEMENTATION,
null,
function(physics){
/**
* Create the plane shape
* @type {GameLib.D3.API.Shape}
*/
var apiShapePlane = new GameLib.D3.API.Shape(
null,
'Shape Plane (' + this.name + ')'
);
apiShapePlane.parentMesh = this;
var shapePlane = new GameLib.D3.Shape.Plane(
physics,
apiShapePlane
);
var apiRigidBody = new GameLib.D3.API.RigidBody(
null,
'Rigid Body (' + this.name + ')',
0,
null,
new GameLib.API.Vector3(
this.position.x,
this.position.y,
this.position.z
),
new GameLib.API.Quaternion(
this.quaternion.x,
this.quaternion.y,
this.quaternion.z,
this.quaternion.w,
new GameLib.API.Vector3(
this.quaternion.axis.x,
this.quaternion.axis.y,
this.quaternion.axis.z
),
this.quaternion.angle
)
);
apiRigidBody.shapes.push(shapePlane);
apiRigidBody.parentMesh = this;
/**
* Construct the rigid body
* @type {GameLib.D3.RigidBody}
*/
var rigidBody = new GameLib.D3.RigidBody(
physics,
apiRigidBody
);
if (this.parentEntity instanceof GameLib.Entity) {
this.parentEntity.addComponent(shapePlane);
this.parentEntity.addComponent(rigidBody);
}
}.bind(this),
function(error){
console.log(error.message);
throw new Error(error.message);
}
);
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @param radius
* @param widthSegments
* @param heightSegments
* @constructor
*/
GameLib.D3.Mesh.Sphere = function (
graphics,
apiMesh,
radius,
widthSegments,
heightSegments
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMesh)) {
apiMesh = {};
}
if (apiMesh instanceof GameLib.D3.Mesh.Box) {
return apiMesh;
}
apiMesh.meshType = GameLib.D3.Mesh.MESH_TYPE_SPHERE;
if (GameLib.Utils.UndefinedOrNull(radius)) {
radius = 1;
}
this.radius = radius;
if (GameLib.Utils.UndefinedOrNull(widthSegments)) {
widthSegments = 5;
}
this.widthSegments = widthSegments;
if (GameLib.Utils.UndefinedOrNull(heightSegments)) {
heightSegments = 5;
}
this.heightSegments = heightSegments;
GameLib.D3.Mesh.call(
this,
this.graphics,
apiMesh
);
};
GameLib.D3.Mesh.Sphere.prototype = Object.create(GameLib.D3.Mesh.prototype);
GameLib.D3.Mesh.Sphere.prototype.constructor = GameLib.D3.Mesh.Sphere;
GameLib.D3.Mesh.Sphere.prototype.createInstance = function() {
var geometry = null;
if (this.vertices.length === 0) {
geometry = new THREE.SphereGeometry(
this.radius,
this.widthSegments,
this.heightSegments
);
this.updateVerticesFromGeometryInstance(geometry);
}
GameLib.D3.Mesh.prototype.createInstance.call(this);
this.instance.userData.radius = this.radius;
this.instance.userData.widthSegments = this.widthSegments;
this.instance.userData.heightSegments = this.heightSegments;
};
GameLib.D3.Mesh.Sphere.prototype.updateInstance = function(property) {
if (
this.instance.userData.widthSegments !== this.widthSegments ||
this.instance.userData.heightSegments !== this.heightSegments ||
this.instance.userData.radius !== this.radius
) {
this.instance.userData.widthSegments = this.widthSegments;
this.instance.userData.heightSegments = this.heightSegments;
this.instance.userData.radius = this.radius;
var geometry = new THREE.SphereGeometry(
this.radius,
this.widthSegments,
this.heightSegments
);
this.updateVerticesFromGeometryInstance(geometry);
geometry = this.createInstanceGeometry();
this.instance.geometry = geometry;
}
GameLib.D3.Mesh.prototype.updateInstance.call(this, property);
};
/**
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.Sphere.prototype.toApiObject = function() {
var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this);
apiMesh.radius = this.radius;
apiMesh.widthSegments = this.widthSegments;
apiMesh.heightSegments = this.heightSegments;
return apiMesh;
};
GameLib.D3.Mesh.Sphere.prototype.createPhysicsObjects = function() {
GameLib.Event.Emit(
GameLib.Event.GET_PHYSICS_IMPLEMENTATION,
null,
function(physics){
var apiShapeSphere = new GameLib.D3.API.Shape(
null,
'Sphere Shape (' + this.name + ')'
);
apiShapeSphere.parentMesh = this;
var shapeSphere = new GameLib.D3.Shape.Sphere(
physics,
apiShapeSphere,
this.radius
);
var apiRigidBody = new GameLib.D3.API.RigidBody(
null,
'Rigid Body (' + this.name + ')',
1,
null,
new GameLib.API.Vector3(
this.position.x,
this.position.y,
this.position.z
),
new GameLib.API.Quaternion(
this.quaternion.x,
this.quaternion.y,
this.quaternion.z,
this.quaternion.w,
new GameLib.API.Vector3(
this.quaternion.axis.x,
this.quaternion.axis.y,
this.quaternion.axis.z
),
this.quaternion.angle
)
);
apiRigidBody.parentMesh = this;
apiRigidBody.shapes.push(shapeSphere);
var rigidBody = new GameLib.D3.RigidBody(
physics,
apiRigidBody
);
if (this.parentEntity instanceof GameLib.Entity) {
this.parentEntity.addComponent(shapeSphere);
this.parentEntity.addComponent(rigidBody);
}
}.bind(this),
function(error){
console.log(error.message);
throw new Error(error.message);
}
);
};
/**
* Converts a standard object mesh to a GameLib.D3.Mesh
* @param graphics GameLib.D3.Graphics
* @param objectMesh {Object}
* @constructor
*/
GameLib.D3.Mesh.Sphere.FromObject = function(graphics, objectMesh) {
var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh);
return new GameLib.D3.Mesh.Sphere(
graphics,
apiMesh,
objectMesh.radius,
objectMesh.widthSegments,
objectMesh.heightSegments
);
};
/**
* Mesh Superset - The apiMesh properties get moved into the Mesh object itself, and then the instance is created
* @param graphics GameLib.D3.Graphics
* @param apiMesh GameLib.D3.API.Mesh
* @param font
* @param size
* @param height
* @param curveSegments
* @param bevelEnabled
* @param bevelThickness
* @param bevelSize
* @param bevelSegments
* @param text
* @constructor
*/
GameLib.D3.Mesh.Text = function (
graphics,
apiMesh,
text,
font,
size,
height,
curveSegments,
bevelEnabled,
bevelThickness,
bevelSize,
bevelSegments
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMesh)) {
apiMesh = {};
}
if (apiMesh instanceof GameLib.D3.Mesh.Box) {
return apiMesh;
}
apiMesh.meshType = GameLib.D3.Mesh.MESH_TYPE_TEXT;
if (GameLib.Utils.UndefinedOrNull(text)) {
text = '-=<yb4f310';
}
this.text = text;
if (GameLib.Utils.UndefinedOrNull(font)) {
font = new GameLib.D3.Font(
this.graphics
);
}
this.font = font;
if (GameLib.Utils.UndefinedOrNull(size)) {
size = 100;
}
this.size = size;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = 50;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(curveSegments)) {
curveSegments = 12;
}
this.curveSegments = curveSegments;
if (GameLib.Utils.UndefinedOrNull(bevelEnabled)) {
bevelEnabled = false;
}
this.bevelEnabled = bevelEnabled;
if (GameLib.Utils.UndefinedOrNull(bevelThickness)) {
bevelThickness = 10;
}
this.bevelThickness = bevelThickness;
if (GameLib.Utils.UndefinedOrNull(bevelSize)) {
bevelSize = 8;
}
this.bevelSize = bevelSize;
if (GameLib.Utils.UndefinedOrNull(bevelSegments)) {
bevelSegments = 3;
}
this.bevelSegments = bevelSegments;
GameLib.D3.Mesh.call(
this,
this.graphics,
apiMesh
);
};
GameLib.D3.Mesh.Text.prototype = Object.create(GameLib.D3.Mesh.prototype);
GameLib.D3.Mesh.Text.prototype.constructor = GameLib.D3.Mesh.Text;
GameLib.D3.Mesh.Text.prototype.createInstance = function() {
var geometry = null;
if (this.vertices.length === 0) {
geometry = new THREE.TextGeometry(
this.text,
{
font: this.font.instance,
size: this.size,
height: this.height,
curveSegments: this.curveSegments,
bevelEnabled: this.bevelEnabled,
bevelThickness: this.bevelThickness,
bevelSize: this.bevelSize,
bevelSegments: this.bevelSegments
}
);
this.updateVerticesFromGeometryInstance(geometry);
}
GameLib.D3.Mesh.prototype.createInstance.call(this);
this.instance.userData.font = this.font;
this.instance.userData.size = this.size;
this.instance.userData.height = this.height;
this.instance.userData.curveSegments = this.curveSegments;
this.instance.userData.bevelEnabled = this.bevelEnabled;
this.instance.userData.bevelThickness = this.bevelThickness;
this.instance.userData.bevelSize = this.bevelSize;
this.instance.userData.bevelSegments = this.bevelSegments;
};
GameLib.D3.Mesh.Text.prototype.updateInstance = function(property) {
if (
this.instance.userData.text !== this.text ||
this.instance.userData.font !== this.font ||
this.instance.userData.size !== this.size ||
this.instance.userData.height !== this.height ||
this.instance.userData.curveSegments !== this.curveSegments ||
this.instance.userData.bevelEnabled !== this.bevelEnabled ||
this.instance.userData.bevelThickness !== this.bevelThickness ||
this.instance.userData.bevelSize !== this.bevelSize ||
this.instance.userData.bevelSegments !== this.bevelSegments
) {
this.instance.userData.text = this.text;
this.instance.userData.font = this.font;
this.instance.userData.size = this.size;
this.instance.userData.height = this.height;
this.instance.userData.curveSegments = this.curveSegments;
this.instance.userData.bevelEnabled = this.bevelEnabled;
this.instance.userData.bevelThickness = this.bevelThickness;
this.instance.userData.bevelSize = this.bevelSize;
this.instance.userData.bevelSegments = this.bevelSegments;
var geometry = new THREE.TextGeometry(
this.text,
{
font: this.font.instance,
size: this.size,
height: this.height,
curveSegments: this.curveSegments,
bevelEnabled: this.bevelEnabled,
bevelThickness: this.bevelThickness,
bevelSize: this.bevelSize,
bevelSegments: this.bevelSegments
}
);
this.updateVerticesFromGeometryInstance(geometry);
geometry = this.createInstanceGeometry();
this.instance.geometry = geometry;
}
GameLib.D3.Mesh.prototype.updateInstance.call(this, property);
};
/**
* Converts a GameLib.D3.Mesh to a GameLib.D3.API.Mesh
* @returns {GameLib.D3.API.Mesh}
*/
GameLib.D3.Mesh.Text.prototype.toApiObject = function() {
var apiMesh = GameLib.D3.Mesh.prototype.toApiObject.call(this);
apiMesh.text = this.text;
apiMesh.font = GameLib.Utils.IdOrNull(this.font);
apiMesh.size = this.size;
apiMesh.height = this.height;
apiMesh.curveSegments = this.curveSegments;
apiMesh.bevelEnabled = this.bevelEnabled;
apiMesh.bevelThickness = this.bevelThickness;
apiMesh.bevelSize = this.bevelSize;
apiMesh.bevelSegments = this.bevelSegments;
return apiMesh;
};
/**
* Converts a standard object mesh to a GameLib.D3.Mesh
* @param graphics GameLib.D3.Graphics
* @param objectMesh {Object}
* @constructor
*/
GameLib.D3.Mesh.Text.FromObject = function(graphics, objectMesh) {
var apiMesh = GameLib.D3.API.Mesh.FromObject(objectMesh);
return new GameLib.D3.Mesh.Text(
graphics,
apiMesh,
objectMesh.text,
objectMesh.font,
objectMesh.size,
objectMesh.height,
objectMesh.curveSegments,
objectMesh.bevelEnabled,
objectMesh.bevelThickness,
objectMesh.bevelSize,
objectMesh.bevelSegments
);
};
/**
* Creates a ParticleEngine object
* @param graphics GameLib.D3.Graphics
* @param apiParticleEngine GameLib.D3.API.ParticleEngine
* @constructor
*/
GameLib.D3.ParticleEngine = function(
graphics,
apiParticleEngine
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiParticleEngine)) {
apiParticleEngine = {};
}
if (apiParticleEngine instanceof GameLib.D3.ParticleEngine) {
return apiParticleEngine;
}
GameLib.D3.API.ParticleEngine.call(
this,
apiParticleEngine.id,
apiParticleEngine.name,
apiParticleEngine.position,
apiParticleEngine.direction,
apiParticleEngine.enabled,
apiParticleEngine.templateParticle,
apiParticleEngine.particlesPerSecond,
apiParticleEngine.frequency,
apiParticleEngine.elapsed,
apiParticleEngine.camera,
apiParticleEngine.pulse,
apiParticleEngine.parentEntity
);
if (this.position instanceof GameLib.API.Vector3) {
this.position = new GameLib.Vector3(
graphics,
this.position,
this
);
} else {
console.warn('position not instance of API.Vector3');
throw new Error('position not instance of API.Vector3');
}
if (this.direction instanceof GameLib.API.Vector3) {
this.direction = new GameLib.Vector3(
graphics,
this.direction,
this
);
} else {
console.warn('direction not instance of API.Vector3');
throw new Error('direction not instance of API.Vector3');
}
if (this.camera instanceof GameLib.D3.API.Camera) {
this.camera = new GameLib.D3.Camera(
graphics,
this.camera
)
}
if (this.templateParticle instanceof GameLib.D3.API.Particle) {
this.templateParticle = new GameLib.D3.Particle(
graphics,
this.templateParticle
)
}
this.particles = [];
this.disabledForRemoval = false;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_PARTICLE_ENGINE,
{
templateParticle : GameLib.D3.Particle,
camera : GameLib.D3.Camera
}
);
};
GameLib.D3.ParticleEngine.prototype = Object.create(GameLib.D3.API.ParticleEngine.prototype);
GameLib.D3.ParticleEngine.prototype.constructor = GameLib.D3.ParticleEngine;
/**
* We don't use a 3rd party particle engine right now
* @returns true
*/
GameLib.D3.ParticleEngine.prototype.createInstance = function() {
this.instance = true;
// if (this.templateParticle) {
//
// this.templateParticle.mesh.position.x = this.position.x;
// this.templateParticle.mesh.position.y = this.position.y;
// this.templateParticle.mesh.position.z = this.position.z;
//
// this.templateParticle.direction.x = this.direction.x;
// this.templateParticle.direction.y = this.direction.y;
// this.templateParticle.direction.z = this.direction.z;
//
// this.templateParticle.scale.x = this.scale.x;
// this.templateParticle.scale.y = this.scale.y;
// this.templateParticle.scale.z = this.scale.z;
// }
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.ParticleEngine.prototype.updateInstance = function(property) {
if (property === 'particlesPerSecond') {
this.frequency = Number(1 / this.particlesPerSecond);
}
if (property === 'frequency') {
this.particlesPerSecond = Math.round(1 / this.frequency);
}
if (property === 'position') {
this.position.instance.x = this.position.x;
this.position.instance.y = this.position.y;
this.position.instance.z = this.position.z;
this.templateParticle.mesh.position = this.position.clone();
this.templateParticle.mesh.updateInstance('position', true);
}
if (property === 'direction') {
this.direction.instance.x = this.direction.x;
this.direction.instance.y = this.direction.y;
this.direction.instance.z = this.direction.z;
this.templateParticle.direction = this.direction.clone();
this.templateParticle.direction.updateInstance('direction', true);
}
};
GameLib.D3.ParticleEngine.prototype.remove = function() {
if (this.removeSubscription) {
console.log('already another remove subscription for ' + this.name);
return;
}
this.removeSubscription = GameLib.Event.Subscribe(
GameLib.Event.REMOVE_PARTICLE_ENGINE,
function(data){
if (data.component === this) {
if (this.isClone) {
/**
* We only remove the things we cloned, the mesh, particle, and this
*/
GameLib.Event.Emit(
GameLib.Event.REMOVE_COMPONENT,
{
component: this.templateParticle.mesh
}
);
GameLib.Event.Emit(
GameLib.Event.REMOVE_COMPONENT,
{
component: this.templateParticle
}
);
GameLib.Event.Emit(
GameLib.Event.REMOVE_COMPONENT,
{
component: this
}
)
} else {
GameLib.Component.prototype.remove.call(this);
}
this.removeSubscription.remove();
this.removeSubscription = null;
}
}.bind(this)
);
/**
* Below signals the particle system to continue processing the particles, but don't create more, and
* we wait for the system to signal REMOVE_PARTICLE_ENGINE so we can destroy ourselves
* @type {boolean}
*/
this.disabledForRemoval = true;
};
// GameLib.D3.ParticleEngine.prototype.getChildrenComponents = function() {
//
// var components = [];
//
// if (this.templateParticle) {
// components.push(this.templateParticle);
//
// if (this.templateParticle.mesh) {
// components.push(this.templateParticle.mesh);
//
// if (this.templateParticle.mesh.materials && this.templateParticle.mesh.materials[0]) {
//
// components.push(this.templateParticle.mesh.materials[0]);
//
// if (this.templateParticle.mesh.materials[0].diffuseMap) {
// components.push(this.templateParticle.mesh.materials[0].diffuseMap);
// }
// }
// }
// }
//
// return components;
// };
GameLib.D3.ParticleEngine.prototype.clone = function() {
var mesh = this.templateParticle.mesh.clone();
var templateParticle = this.templateParticle.clone();
templateParticle.mesh = mesh;
templateParticle.instance = mesh.instance;
var engine = GameLib.Component.prototype.clone.call(this);
engine.templateParticle = templateParticle;
return engine;
};
GameLib.D3.ParticleEngine.prototype.processParticles = function(delta) {
// this.particles = this.particles.reduce(
// function(result, particle){
//
// particle.position.x += particle.userData.direction.x * delta;
// particle.position.y += particle.userData.direction.y * delta;
// particle.position.z += particle.userData.direction.z * delta;
//
// particle.userData.elapsed += delta;
// if (particle.userData.elapsed > particle.userData.lifeTime) {
// particle.parent.remove(particle);
// } else {
// result.push(particle);
// }
//
// return result;
// },
// []
// );
};
GameLib.D3.ParticleEngine.prototype.createNewParticle = function(camera) {
//
// var particle = this.templateParticle.clone(camera);
//
// this.particles.push(particle);
};
/**
* Converts a GameLib.D3.ParticleEngine to a new GameLib.D3.API.ParticleEngine
* @returns {GameLib.D3.API.ParticleEngine}
*/
GameLib.D3.ParticleEngine.prototype.toApiObject = function() {
return new GameLib.D3.API.ParticleEngine(
this.id,
this.name,
this.position.toApiObject(),
this.direction.toApiObject(),
this.enabled,
GameLib.Utils.IdOrNull(this.templateParticle),
this.particlesPerSecond,
this.frequency,
this.elapsed,
GameLib.Utils.IdOrNull(this.camera),
this.pulse,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts from an Object ParticleEngine to a GameLib.D3.ParticleEngine
* @param graphics GameLib.D3.Graphics
* @param objectParticleEngine Object
* @returns {GameLib.D3.ParticleEngine}
* @constructor
*/
GameLib.D3.ParticleEngine.FromObject = function(graphics, objectParticleEngine) {
var apiParticleEngine = GameLib.D3.API.ParticleEngine.FromObject(objectParticleEngine);
return new GameLib.D3.ParticleEngine(
graphics,
apiParticleEngine
);
};
/**
* Creates a Particle object
* @param graphics GameLib.D3.Graphics
* @param apiParticle GameLib.D3.API.Particle
* @constructor
*/
GameLib.D3.Particle = function(
graphics,
apiParticle
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiParticle)) {
apiParticle = {};
}
if (apiParticle instanceof GameLib.D3.Particle) {
return apiParticle;
}
GameLib.D3.API.Particle.call(
this,
apiParticle.id,
apiParticle.name,
apiParticle.lifeTime,
apiParticle.elapsed,
apiParticle.mesh,
apiParticle.opacityType,
apiParticle.opacityFactor,
apiParticle.positionOffsetType,
apiParticle.positionOffset,
apiParticle.positionOffsetFn,
apiParticle.directionType,
apiParticle.direction,
apiParticle.directionFn,
apiParticle.speedType,
apiParticle.speed,
apiParticle.scaleType,
apiParticle.scale,
apiParticle.scaleFn,
apiParticle.rotationType,
apiParticle.rotation,
apiParticle.rotationFn,
apiParticle.parentEngine,
apiParticle.parentEntity
);
if (this.mesh instanceof GameLib.D3.API.Mesh) {
this.mesh = new GameLib.D3.Mesh(
graphics,
this.mesh
)
}
if (this.positionOffset instanceof GameLib.API.Vector3) {
this.positionOffset = new GameLib.Vector3(
graphics,
this.positionOffset,
this
);
} else {
console.warn('positionOffset not instance of API.Vector3');
throw new Error('positionOffset not instance of API.Vector3');
}
if (this.direction instanceof GameLib.API.Vector3) {
this.direction = new GameLib.Vector3(
graphics,
this.direction,
this
);
} else {
console.warn('direction not instance of API.Vector3');
throw new Error('direction not instance of API.Vector3');
}
if (this.scale instanceof GameLib.API.Vector3) {
this.scale = new GameLib.Vector3(
graphics,
this.scale,
this
);
} else {
console.warn('scale not instance of API.Vector3');
throw new Error('scale not instance of API.Vector3');
}
if (this.rotation instanceof GameLib.API.Vector3) {
this.rotation = new GameLib.Vector3(
graphics,
this.rotation,
this
);
} else {
console.warn('rotation not instance of API.Vector3');
throw new Error('rotation not instance of API.Vector3');
}
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_PARTICLE,
{
mesh : GameLib.D3.Mesh,
parentEngine : GameLib.D3.ParticleEngine
}
);
};
GameLib.D3.Particle.prototype = Object.create(GameLib.D3.API.Particle.prototype);
GameLib.D3.Particle.prototype.constructor = GameLib.D3.Particle;
GameLib.D3.Particle.OPACITY_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.OPACITY_TYPE_DECREASE_LINEAR = 0x2;
GameLib.D3.Particle.OPACITY_TYPE_INCREASE_LINEAR = 0x3;
GameLib.D3.Particle.POSITION_OFFSET_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.POSITION_OFFSET_TYPE_RANDOM = 0x2;
GameLib.D3.Particle.POSITION_OFFSET_TYPE_FUNCTION = 0x3;
GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.DIRECTION_TYPE_RANDOM = 0x2;
GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED = 0x3;
GameLib.D3.Particle.DIRECTION_TYPE_FUNCTION = 0x4;
GameLib.D3.Particle.SCALE_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.SCALE_TYPE_LINEAR = 0x2;
GameLib.D3.Particle.SCALE_TYPE_EXPONENTIAL = 0x3;
GameLib.D3.Particle.SCALE_TYPE_RANDOM = 0x4;
GameLib.D3.Particle.SCALE_TYPE_RANDOM_X_EQUALS_Y = 0x6;
GameLib.D3.Particle.SCALE_TYPE_FUNCTION = 0x7;
GameLib.D3.Particle.SPEED_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.SPEED_TYPE_LINEAR = 0x2;
GameLib.D3.Particle.SPEED_TYPE_EXPONENTIAL = 0x3;
GameLib.D3.Particle.SPEED_TYPE_LOGARITHMIC = 0x4;
GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_LOG = 0x5;
GameLib.D3.Particle.SPEED_TYPE_EXP = 0x6;
GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_EXP = 0x7;
GameLib.D3.Particle.ROTATION_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.ROTATION_TYPE_RANDOM = 0x2;
GameLib.D3.Particle.ROTATION_TYPE_FUNCTION = 0x3;
/**
* Particle create instance
*/
GameLib.D3.Particle.prototype.createInstance = function() {
if (!this.mesh) {
console.warn('no mesh to clone from - failed dependency check?');
return
}
this.instance = this.mesh.instance;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Particle.prototype.updateInstance = function(property) {
if (property === 'positionOffset') {
this.positionOffset.instance.x = this.positionOffset.x;
this.positionOffset.instance.y = this.positionOffset.y;
this.positionOffset.instance.z = this.positionOffset.z;
}
if (property === 'direction') {
this.direction.instance.x = this.direction.x;
this.direction.instance.y = this.direction.y;
this.direction.instance.z = this.direction.z;
}
if (property === 'scale') {
this.scale.instance.x = this.scale.x;
this.scale.instance.y = this.scale.y;
this.scale.instance.z = this.scale.z;
}
if (property === 'rotation') {
this.rotation.instance.x = this.rotation.x;
this.rotation.instance.y = this.rotation.y;
this.rotation.instance.z = this.rotation.z;
}
};
/**
* Clones a particle - this only clones 3rd party instances, so we have less overhead of creating these types of objects
*/
GameLib.D3.Particle.prototype.cloneInstance = function() {
this.updateInstance('positionOffset');
this.updateInstance('direction');
this.updateInstance('scale');
this.updateInstance('rotation');
var clone = GameLib.Component.prototype.cloneInstance.call(this);
clone.position = this.parentEngine.position.instance.clone();
clone.material = this.mesh.materials[0].instance.clone();
clone.visible = true;
if (this.positionOffsetType === GameLib.D3.Particle.POSITION_OFFSET_TYPE_CONSTANT) {
clone.position.add(this.positionOffset.instance);
}
var addX = 1;
var addY = 1;
var addZ = 1;
if (this.positionOffsetType === GameLib.D3.Particle.POSITION_OFFSET_TYPE_RANDOM) {
addX = GameLib.Utils.GetRandomIntInclusive(1,2);
addY = GameLib.Utils.GetRandomIntInclusive(1,2);
addZ = GameLib.Utils.GetRandomIntInclusive(1,2);
if (addX === 1) {
clone.position.x += Math.random() * this.positionOffset.x;
} else {
clone.position.x -= Math.random() * this.positionOffset.x;
}
if (addY === 1) {
clone.position.y -= Math.random() * this.positionOffset.y;
} else {
clone.position.y += Math.random() * this.positionOffset.y;
}
if (addZ === 1) {
clone.position.z -= Math.random() * this.positionOffset.z;
} else {
clone.position.z += Math.random() * this.positionOffset.z;
}
}
clone.userData.direction = this.direction.clone();
if (this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT) {
/**
* Nothing to do
*/
} else if (
this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM ||
this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED
) {
addX = GameLib.Utils.GetRandomIntInclusive(1,2);
addY = GameLib.Utils.GetRandomIntInclusive(1,2);
addZ = GameLib.Utils.GetRandomIntInclusive(1,2);
clone.userData.direction.x = 0;
clone.userData.direction.y = 0;
clone.userData.direction.z = 0;
if (addX === 1) {
clone.userData.direction.x += Math.random() * this.direction.x;
} else {
clone.userData.direction.x -= Math.random() * this.direction.x;
}
if (addY === 1) {
clone.userData.direction.y -= Math.random() * this.direction.y;
} else {
clone.userData.direction.y += Math.random() * this.direction.y;
}
if (addZ === 1) {
clone.userData.direction.z -= Math.random() * this.direction.z;
} else {
clone.userData.direction.z += Math.random() * this.direction.z;
}
if (this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED) {
clone.userData.direction.normalize();
}
} else {
throw new Error('not yet implemented')
}
if (this.scaleType === GameLib.D3.Particle.SCALE_TYPE_CONSTANT) {
clone.scale.x += this.scale.x;
clone.scale.y += this.scale.y;
clone.scale.z += this.scale.z;
}
if (this.scaleType === GameLib.D3.Particle.SCALE_TYPE_RANDOM) {
add = GameLib.Utils.GetRandomIntInclusive(1,2);
if (add === 1) {
clone.scale.x += Math.random() * this.scale.x;
clone.scale.y += Math.random() * this.scale.y;
clone.scale.z += Math.random() * this.scale.z;
} else {
clone.scale.x -= Math.random() * this.scale.x;
clone.scale.y -= Math.random() * this.scale.y;
clone.scale.z -= Math.random() * this.scale.z;
}
}
if (this.scaleType === GameLib.D3.Particle.SCALE_TYPE_RANDOM_X_EQUALS_Y) {
add = GameLib.Utils.GetRandomIntInclusive(1,2);
var factor = Math.random() * this.scale.x;
if (add === 1) {
clone.scale.x += factor;
clone.scale.y += factor;
clone.scale.z += Math.random() * this.scale.z;
} else {
clone.scale.x -= factor;
clone.scale.y -= factor;
clone.scale.z -= Math.random() * this.scale.z;
}
}
clone.userData.scale = this.scale.clone();
clone.userData.lifeTime = this.lifeTime;
clone.userData.speedType = this.speedType;
clone.userData.speed = this.speed;
clone.userData.scene = this.mesh.parentScene.instance;
clone.userData.elapsed = 0;
clone.userData.scene.add(clone);
return clone;
};
/**
* Converts a GameLib.D3.Particle to a new GameLib.D3.API.Particle
* @returns {GameLib.D3.API.Particle}
*/
GameLib.D3.Particle.prototype.toApiObject = function() {
return new GameLib.D3.API.Particle(
this.id,
this.name,
this.lifeTime,
this.elapsed,
GameLib.Utils.IdOrNull(this.mesh),
this.opacityType,
this.opacityFactor,
this.positionOffsetType,
this.positionOffset.toApiObject(),
this.positionOffsetFn,
this.directionType,
this.direction.toApiObject(),
this.directionFn,
this.speedType,
this.speed,
this.scaleType,
this.scale.toApiObject(),
this.scaleFn,
this.rotationType,
this.rotation.toApiObject(),
this.rotationFn,
GameLib.Utils.IdOrNull(this.parentEngine),
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts from an Object Particle to a GameLib.D3.Particle
* @param graphics GameLib.D3.Graphics
* @param objectParticle Object
* @returns {GameLib.D3.Particle}
* @constructor
*/
GameLib.D3.Particle.FromObject = function(graphics, objectParticle) {
var apiParticle = GameLib.D3.API.Particle.FromObject(objectParticle);
return new GameLib.D3.Particle(
graphics,
apiParticle
);
};
/**
* Renders a scene with a camera
* @param graphics GameLib.D3.Graphics
* @param apiPass GameLib.D3.API.Pass
* @constructor
*/
GameLib.D3.Pass = function (
graphics,
apiPass
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiPass)) {
apiPass = {};
}
if (apiPass instanceof GameLib.D3.Pass) {
return apiPass;
}
GameLib.D3.API.Pass.call(
this,
apiPass.id,
apiPass.name,
apiPass.passType,
apiPass.camera,
apiPass.scene,
apiPass.renderToScreen,
apiPass.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_PASS,
{
'camera' : GameLib.D3.Camera,
'scene' : GameLib.D3.Scene
}
);
};
GameLib.D3.Pass.prototype = Object.create(GameLib.D3.API.Pass.prototype);
GameLib.D3.Pass.prototype.constructor = GameLib.D3.Pass;
GameLib.D3.Pass.PASS_TYPE_RENDER = 0x1;
GameLib.D3.Pass.PASS_TYPE_COPY_SHADER = 0x2;
/**
* Create Pass instance
* @returns {*}
*/
GameLib.D3.Pass.prototype.createInstance = function() {
if (this.passType === GameLib.D3.Pass.PASS_TYPE_RENDER) {
if (GameLib.Utils.UndefinedOrNull(this.scene)) {
throw new Error('no scene object');
}
if (GameLib.Utils.UndefinedOrNull(this.camera)) {
throw new Error('no camera object');
}
if (GameLib.Utils.UndefinedOrNull(THREE.RenderPass)) {
throw new Error('no render pass library')
}
this.instance = new THREE.RenderPass(
this.scene.instance,
this.camera.instance
);
} else if (this.passType === GameLib.D3.Pass.PASS_TYPE_COPY_SHADER) {
if (GameLib.Utils.UndefinedOrNull(THREE.CopyShader)) {
throw new Error('no copyshader library')
}
this.instance = THREE.CopyShader;
} else {
console.warn('Render pass not supported yet: ' + this.passType);
throw new Error('Render pass not supported yet: ' + this.passType);
}
this.instance.renderToScreen = this.renderToScreen;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Update Pass instance
*/
GameLib.D3.Pass.prototype.updateInstance = function() {
if (
this.passType === GameLib.D3.Pass.PASS_TYPE_RENDER && !(this.instance instanceof THREE.RenderPass)){
this.createInstance();
}
if (
this.passType === GameLib.D3.Pass.PASS_TYPE_COPY_SHADER && !(this.instance instanceof THREE.CopyShader)){
this.createInstance();
}
this.instance.renderToScreen = this.renderToScreen;
};
/**
* GameLib.D3.Pass to GameLib.D3.API.Pass
* @returns {GameLib.D3.API.Pass}
*/
GameLib.D3.Pass.prototype.toApiObject = function() {
var apiPass = new GameLib.D3.API.Pass(
this.id,
this.name,
this.passType,
GameLib.Utils.IdOrNull(this.camera),
GameLib.Utils.IdOrNull(this.scene),
this.renderToScreen,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiPass;
};
/**
* GameLib.D3.Pass from Object
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.Pass}
* @constructor
*/
GameLib.D3.Pass.FromObject = function(graphics, objectComponent) {
var apiPass = GameLib.D3.API.Pass.FromObject(objectComponent);
return new GameLib.D3.Pass(
graphics,
apiPass
);
};
/**
* This component makes the parentEntity (ex. car) follow the path provided by the spline
* @param graphics GameLib.D3.Graphics
* @param apiPathFollowing GameLib.D3.API.PathFollowing
* @constructor
*/
GameLib.D3.PathFollowing = function (
graphics,
apiPathFollowing
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiPathFollowing)) {
apiPathFollowing = {};
}
if (apiPathFollowing instanceof GameLib.D3.PathFollowing) {
return apiPathFollowing;
}
GameLib.D3.API.PathFollowing.call(
this,
apiPathFollowing.id,
apiPathFollowing.name,
apiPathFollowing.spline,
apiPathFollowing.mesh,
apiPathFollowing.raytraceMesh,
apiPathFollowing.accelleration,
apiPathFollowing.maxSpeed,
apiPathFollowing.baseOffset,
apiPathFollowing.maxOffset,
apiPathFollowing.steeringSpeed,
apiPathFollowing.targetOffset,
apiPathFollowing.currentOffset,
apiPathFollowing.currentPathValue,
apiPathFollowing.currentSpeed,
apiPathFollowing.direction,
apiPathFollowing.raycaster,
apiPathFollowing.currentPosition,
apiPathFollowing.futurePosition,
apiPathFollowing.up,
apiPathFollowing.rotationMatrix,
apiPathFollowing.rotationVector,
apiPathFollowing.parentEntity
);
this.baseOffset = new GameLib.Vector3(
this.graphics,
this.baseOffset,
this
);
this.maxOffset = new GameLib.Vector3(
this.graphics,
this.maxOffset,
this
);
this.targetOffset = new GameLib.Vector3(
this.graphics,
this.targetOffset,
this
);
this.currentOffset = new GameLib.Vector3(
this.graphics,
this.currentOffset,
this
);
this.raycaster = new GameLib.D3.Raycaster(
this.graphics,
this.raycaster
);
this.currentPosition = new GameLib.Vector3(
this.graphics,
this.currentPosition,
this
);
this.futurePosition = new GameLib.Vector3(
this.graphics,
this.futurePosition,
this
);
this.up = new GameLib.Vector3(
this.graphics,
this.up,
this
);
this.rotationMatrix = new GameLib.Matrix4(
this.graphics,
this.rotationMatrix,
this
);
this.rotationVector = new GameLib.Quaternion(
this.graphics,
this.rotationVector,
this
);
this.mx = new GameLib.Utils.MovingAverage(10);
this.my = new GameLib.Utils.MovingAverage(10);
this.mz = new GameLib.Utils.MovingAverage(10);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_PATH_FOLLOWING,
{
'spline': GameLib.D3.Spline,
'mesh' : GameLib.D3.Mesh,
'raytraceMesh' : GameLib.D3.Mesh
}
);
};
GameLib.D3.PathFollowing.prototype = Object.create(GameLib.D3.API.PathFollowing.prototype);
GameLib.D3.PathFollowing.prototype.constructor = GameLib.D3.PathFollowing;
GameLib.D3.PathFollowing.prototype.createInstance = function() {
console.log('GameLib.D3.PathFollowing.prototype.createInstance()');
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.PathFollowing.prototype.toApiObject = function() {
var apiPathFollowing = new GameLib.D3.API.PathFollowing(
this.id,
this.name,
GameLib.Utils.IdOrNull(this.spline),
GameLib.Utils.IdOrNull(this.mesh),
GameLib.Utils.IdOrNull(this.raytraceMesh),
this.accelleration,
this.maxSpeed,
this.baseOffset.toApiObject(),
this.maxOffset.toApiObject(),
this.steeringSpeed,
this.targetOffset.toApiObject(),
this.currentOffset.toApiObject(),
this.currentPathValue,
this.currentSpeed,
this.direction,
this.raycaster.toApiObject(),
this.currentPosition.toApiObject(),
this.futurePosition.toApiObject(),
this.up.toApiObject(),
this.rotationMatrix.toApiObject(),
this.rotationVector.toApiObject(),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiPathFollowing;
};
/**
* Object path following to GameLib.D3.PathFollowing
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.PathFollowing}
* @constructor
*/
GameLib.D3.PathFollowing.FromObject = function(graphics, objectComponent) {
var apiPathFollowing = GameLib.D3.API.PathFollowing.FromObject(objectComponent);
return new GameLib.D3.PathFollowing(
graphics,
apiPathFollowing
);
};
/**
* Updates the component
* @param deltaTime
*/
GameLib.D3.PathFollowing.prototype.update = function(deltaTime) {
if (this.spline && this.mesh && this.raytraceMesh) {
this.currentSpeed += this.accelleration * deltaTime * this.direction;
if(this.currentSpeed > this.maxSpeed) {
this.currentSpeed = this.maxSpeed;
}
this.grain = (this.currentSpeed / 100.0);
var currentPosition = this.spline.getPointAt(this.currentPathValue);
this.currentPosition.x = currentPosition.x;
this.currentPosition.y = currentPosition.y;
this.currentPosition.z = currentPosition.z;
this.currentPathValue += this.grain;
if (this.currentPathValue >= 1) {
this.currentPathValue = this.currentPathValue - 1;
}
if (this.currentPathValue < 0) {
this.currentPathValue = 0.0;
}
var futurePosition = this.spline.getPointAt(this.currentPathValue);
this.futurePosition.x = futurePosition.x;
this.futurePosition.y = futurePosition.y;
this.futurePosition.z = futurePosition.z;
this.raycaster.setPosition(
this.currentPosition
);
this.raycaster.setDirection(
{
x : -this.up.x,
y : -this.up.y,
z : -this.up.z
}
);
var normal = this.raycaster.getFaceNormal(this.raytraceMesh);
if (normal) {
this.up.x = this.mx(normal.x);
this.up.y = this.my(normal.y);
this.up.z = this.mz(normal.z);
}
this.rotationMatrix.lookAt(
this.currentPosition,
this.futurePosition,
this.up
);
this.rotationVector.setFromRotationMatrix(this.rotationMatrix);
this.mesh.position.x = this.futurePosition.x;
this.mesh.position.y = this.futurePosition.y;
this.mesh.position.z = this.futurePosition.z;
/**
* Update Rotation
*/
this.mesh.quaternion.x = this.rotationVector.x;
this.mesh.quaternion.y = this.rotationVector.y;
this.mesh.quaternion.z = this.rotationVector.z;
this.mesh.quaternion.w = this.rotationVector.w;
}
};
/**
* World SuperSet - contains the custom world instance
* @constructor
* @param physics
* @param apiWorld
*/
GameLib.D3.PhysicsWorld = function(
physics,
apiWorld
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiWorld)) {
apiWorld = {};
}
if (apiWorld instanceof GameLib.D3.PhysicsWorld) {
return apiWorld;
}
GameLib.D3.API.PhysicsWorld.call(
this,
apiWorld.id,
apiWorld.name,
apiWorld.gravity,
apiWorld.broadphase,
apiWorld.solver,
apiWorld.rigidBodies,
apiWorld.contactMaterials,
apiWorld.allowSleep,
apiWorld.defaultContactMaterial,
apiWorld.parentEntity
);
if (this.gravity instanceof GameLib.API.Vector3) {
this.gravity = new GameLib.Vector3(
this.physics,
this.gravity,
this
);
}
if (this.broadphase instanceof GameLib.D3.API.Broadphase) {
this.broadphase = new GameLib.D3.Broadphase(
this.physics,
this.broadphase
);
}
if (this.solver instanceof GameLib.D3.API.Solver) {
this.solver = new GameLib.D3.Solver(
this.physics,
this.solver
);
}
this.rigidBodies = this.rigidBodies.map(
function(rigidBody) {
if (rigidBody instanceof GameLib.D3.API.RigidBody) {
return new GameLib.D3.RigidBody(
this.physics,
rigidBody
);
}
return rigidBody;
}.bind(this)
);
this.contactMaterials = this.contactMaterials.map(
function(contactMaterial) {
if (contactMaterial instanceof GameLib.D3.API.FrictionContactMaterial) {
return new GameLib.D3.FrictionContactMaterial(
this.physics,
contactMaterial
);
}
return contactMaterial;
}.bind(this)
);
if (this.defaultContactMaterial instanceof GameLib.D3.API.FrictionContactMaterial) {
this.defaultContactMaterial = new GameLib.D3.FrictionContactMaterial(
this.physics,
this.defaultContactMaterial
)
}
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_PHYSICS_WORLD,
{
'broadphase' : GameLib.D3.Broadphase,
'solver' : GameLib.D3.Solver,
'rigidBodies' : [GameLib.D3.RigidBody],
'contactMaterials' : [GameLib.D3.FrictionContactMaterial],
'defaultContactMaterial' : GameLib.D3.FrictionContactMaterial
}
);
};
GameLib.D3.PhysicsWorld.prototype = Object.create(GameLib.D3.API.PhysicsWorld.prototype);
GameLib.D3.PhysicsWorld.prototype.constructor = GameLib.D3.PhysicsWorld;
/**
* private
* @returns {GameLib.D3.PhysicsWorld|GameLib.D3.Physics.World|*}
*/
GameLib.D3.PhysicsWorld.prototype.createInstance = function() {
if (GameLib.Utils.UndefinedOrNull(this.broadphase)) {
throw new Error('no broadphase');
}
if (GameLib.Utils.UndefinedOrNull(this.broadphase.instance)) {
throw new Error('no broadphase instance');
}
if (GameLib.Utils.UndefinedOrNull(this.solver)) {
throw new Error('no solver');
}
if (GameLib.Utils.UndefinedOrNull(this.solver.instance)) {
throw new Error('no solver instance');
}
this.instance = new CANNON.World();
this.instance.broadphase = this.broadphase.instance;
this.instance.solver = this.solver.instance;
this.instance.gravity = this.gravity.instance;
this.instance.allowSleep = this.allowSleep;
this.contactMaterials.map(
function (contactMaterial) {
if (GameLib.Utils.UndefinedOrNull(contactMaterial)) {
throw new Error('no contact material');
}
if (GameLib.Utils.UndefinedOrNull(contactMaterial.instance)) {
throw new Error('no contact material instance');
}
this.instance.addContactMaterial(contactMaterial.instance);
}.bind(this)
);
this.rigidBodies.map(
function (rigidBody) {
if (GameLib.Utils.UndefinedOrNull(rigidBody)) {
throw new Error('no rigidbody');
}
if (GameLib.Utils.UndefinedOrNull(rigidBody.instance)) {
throw new Error('no rigidbody instance');
}
rigidBody.parentWorld = this;
this.instance.add(rigidBody.instance);
}.bind(this)
);
this.instance.defaultContactMaterial.friction = this.defaultContactMaterial.friction;
this.instance.defaultContactMaterial.restitution = this.defaultContactMaterial.restitution;
this.instance.defaultContactMaterial.contactEquationStiffness = this.defaultContactMaterial.contactEquationStiffness;
this.instance.defaultContactMaterial.contactEquationRelaxation = this.defaultContactMaterial.contactEquationRelaxation;
this.instance.defaultContactMaterial.frictionEquationStiffness = this.defaultContactMaterial.frictionEquationStiffness;
this.instance.defaultContactMaterial.frictionEquationRelaxation = this.defaultContactMaterial.frictionEquationRelaxation;
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.PhysicsWorld.prototype.addRigidBody = function(rigidBody) {
if (rigidBody && rigidBody.instance) {
/**
* Add the rigid body to the instance world
*/
this.instance.add(rigidBody.instance);
/**
* Remember to set the parentWorld for this rigidBody
* @type {GameLib.D3.PhysicsWorld}
*/
rigidBody.parentWorld = this;
/**
* Ensure this rigidBody is in our rigidBodies array, just not too many times..
*/
GameLib.Utils.PushUnique(this.rigidBodies, rigidBody);
} else {
console.warn('Attempt to add rigidBody ' + rigidBody.name + ' without an instance');
}
};
/**
*
* @param rigidBody
*/
GameLib.D3.PhysicsWorld.prototype.removeRigidBody = function(rigidBody) {
if (!rigidBody instanceof GameLib.D3.RigidBody) {
console.warn('not a rigid body');
return;
}
/**
* Remove the instance
*/
if (rigidBody.instance) {
this.instance.remove(rigidBody.instance);
} else {
console.warn('Attempt to remove rigidBody ' + rigidBody.name + ' without an instance');
}
/**
* Remember to set the parentWorld for this rigidBody
* @type {GameLib.D3.PhysicsWorld}
*/
rigidBody.parentWorld = null;
/**
* Remove from this rigidBodies array
*/
var index = this.rigidBodies.indexOf(rigidBody);
if (index !== -1) {
this.rigidBodies.splice(index, 1);
} else {
console.warn('could not remove a rigidbody from an array where it should have existed');
}
};
/**
*
*/
GameLib.D3.PhysicsWorld.prototype.updateInstance = function() {
if (!this.instance) {
console.log('no world instance');
return;
}
this.instance.broadphase = this.broadphase.instance;
this.instance.solver = this.solver.instance;
this.instance.gravity = this.gravity.instance;
this.instance.allowSleep = this.allowSleep;
this.instance.defaultContactMaterial.friction = this.defaultContactMaterial.friction;
this.instance.defaultContactMaterial.restitution = this.defaultContactMaterial.restitution;
this.instance.defaultContactMaterial.contactEquationStiffness = this.defaultContactMaterial.contactEquationStiffness;
this.instance.defaultContactMaterial.contactEquationRelaxation = this.defaultContactMaterial.contactEquationRelaxation;
this.instance.defaultContactMaterial.frictionEquationStiffness = this.defaultContactMaterial.frictionEquationStiffness;
this.instance.defaultContactMaterial.frictionEquationRelaxation = this.defaultContactMaterial.frictionEquationRelaxation;
};
/**
* GameLib.D3.PhysicsWorld to GameLib.D3.API.PhysicsWorld
* @returns {GameLib.D3.API.PhysicsWorld}
*/
GameLib.D3.PhysicsWorld.prototype.toApiObject = function() {
var apiWorld = new GameLib.D3.API.PhysicsWorld(
this.id,
this.name,
this.gravity.toApiObject(),
GameLib.Utils.IdOrNull(this.broadphase),
GameLib.Utils.IdOrNull(this.solver),
this.rigidBodies.map(function(body){
return GameLib.Utils.IdOrNull(body);
}),
this.contactMaterials.map(function(contactMaterial){
return GameLib.Utils.IdOrNull(contactMaterial);
}),
this.allowSleep,
GameLib.Utils.IdOrNull(this.defaultContactMaterial),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiWorld;
};
/**
* GameLib.D3.PhysicsWorld from Object World
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.PhysicsWorld}
* @constructor
*/
GameLib.D3.PhysicsWorld.FromObject = function(graphics, objectComponent) {
var apiWorld = GameLib.D3.API.PhysicsWorld.FromObject(objectComponent);
return new GameLib.D3.PhysicsWorld(
graphics,
apiWorld
);
};
//
// GameLib.D3.PhysicsWorld.prototype.step = function(
// fixedStep,
// dtStep
// ) {
//
// };
//
// GameLib.D3.PhysicsWorld.prototype.generateWireframeViewTriangleMesh = function(
// graphics,
// triangleMeshShape,
// normalLength,
// scale,
// opacity,
// wireframeColor
// ) {
// graphics.isNotThreeThrow();
// this.engine.isNotCannonThrow();
//
// if(typeof normalLength == 'undefined') {
// normalLength = 10;
// }
//
// if(typeof scale == 'undefined') {
// scale = new graphics.instance.Vector3(1, 1, 1);
// }
//
// if(typeof opacity == 'undefined') {
// opacity = 0.5;
// }
//
// if(typeof wireframeColor == 'undefined') {
// wireframeColor = 0xfefefe;
// }
//
// var graphicsGeometry = new graphics.instance.Geometry();
//
// var wireframeMesh = new graphics.instance.Mesh(
// graphicsGeometry,
// new graphics.instance.MeshBasicMaterial({
// color: wireframeColor,
// wireframe: true,
// opacity: opacity
// })
// );
//
// for(var v = 0, l = triangleMeshShape.instance.vertices.length / 3; v < l; ++v) {
// graphicsGeometry.vertices.push(
// new graphics.instance.Vector3(
// triangleMeshShape.instance.vertices[v * 3],
// triangleMeshShape.instance.vertices[v * 3 + 1],
// triangleMeshShape.instance.vertices[v * 3 + 2]
// )
// );
// }
//
// for(var i = 0, l = triangleMeshShape.instance.indices.length / 3; i < l; ++i) {
// var i0 = triangleMeshShape.instance.indices[i * 3];
// var i1 = triangleMeshShape.instance.indices[i * 3 + 1];
// var i2 = triangleMeshShape.instance.indices[i * 3 + 2];
//
// graphicsGeometry.faces.push(
// new graphics.instance.Face3(
// i0,
// i1,
// i2
// )
// );
//
// // Center point on the current triangle
//
// var centroid = new graphics.instance.Vector3()
// .add(graphicsGeometry.vertices[i0])
// .add(graphicsGeometry.vertices[i1])
// .add(graphicsGeometry.vertices[i2])
// .divideScalar(3);
//
// // Get the normal from the mesh shape itself
// var normal = new this.engine.instance.Vec3();
// triangleMeshShape.instance.getNormal(i , normal);
//
// var arrow = new graphics.instance.ArrowHelper(
// new graphics.instance.Vector3(
// normal.x,
// normal.y,
// normal.z
// ),
// centroid,
// normalLength,
// new graphics.instance.Color(
// normal.x,
// normal.y,
// normal.z
// )
// );
// wireframeMesh.add( arrow );
// }
//
// wireframeMesh.scale.x = scale.x;
// wireframeMesh.scale.y = scale.y;
// wireframeMesh.scale.z = scale.z;
//
// return wireframeMesh;
// };
//
// /**
// * @param convexPolyMeshShape GameLib.D3.Shape
// * @param normalLength Number
// * @param scale GameLib.API.Vector3
// * @param opacity Number
// * @param wireframeColor HexCode
// * @param graphics THREE
// * @returns {THREE.Mesh|this.meshes}
// * @constructor
// */
// GameLib.D3.PhysicsWorld.prototype.generateWireframeViewConvexPolyMesh = function(
// graphics,
// convexPolyMeshShape,
// normalLength,
// scale,
// opacity,
// wireframeColor
// ) {
// graphics.isNotThreeThrow();
// this.engine.isNotCannonThrow();
//
// if(typeof normalLength == 'undefined') {
// normalLength = 10;
// }
//
// if(typeof scale == 'undefined') {
// scale = new graphics.instance.Vector3(1, 1, 1);
// }
//
// if(typeof opacity == 'undefined') {
// opacity = 0.5;
// }
//
// if(typeof wireframeColor == 'undefined') {
// wireframeColor = 0xfefefe;
// }
//
//
// var graphicsGeometry = new graphics.instance.Geometry();
// var wireframeMesh = new graphics.instance.Mesh(
// graphicsGeometry,
// new graphics.instance.MeshBasicMaterial({
// color: wireframeColor,
// wireframe: true,
// opacity: opacity
// })
// );
//
// for(var i = 0, l = convexPolyMeshShape.instance.vertices.length; i < l; i++) {
// var vertex = convexPolyMeshShape.instance.vertices[i];
// graphicsGeometry.vertices.push(new graphics.instance.Vector3(vertex.x, vertex.y, vertex.z));
// }
//
// for(var i = 0, l = convexPolyMeshShape.instance.faces.length; i < l; i++) {
// var face = convexPolyMeshShape.instance.faces[i];
//
// var i0 = face[0];
// var i1 = face[1];
// var i2 = face[2];
//
// graphicsGeometry.faces.push(new graphics.instance.Face3(i0, i1, i2));
//
// // Center point on the current triangle
// var centroid = new graphics.instance.Vector3()
// .add(graphicsGeometry.vertices[i0])
// .add(graphicsGeometry.vertices[i1])
// .add(graphicsGeometry.vertices[i2])
// .divideScalar(3);
//
// var normalVec3 = convexPolyMeshShape.instance.faceNormals[i];
// var normal = new graphics.instance.Vector3(
// normalVec3.x,
// normalVec3.y,
// normalVec3.z
// );
//
// var arrow = new graphics.instance.ArrowHelper(
// normal,
// centroid,
// normalLength,
// new graphics.instance.Color(
// normal.x,
// normal.y,
// normal.z
// )
// );
//
// wireframeMesh.add( arrow );
// }
//
// wireframeMesh.scale.x = scale.x;
// wireframeMesh.scale.y = scale.y;
// wireframeMesh.scale.z = scale.z;
//
// return wireframeMesh;
// };
//
// /**
// * @param graphics GameLib.D3.Graphics
// * @param graphicsMesh THREE.Mesh
// * @param mass Number
// * @param friction Number
// * @param createCollisionSubMeshes Boolean
// * @param facesPerSubsection Number
// * @param subsectionsToMerge Number
// * @returns {Object}
// * @constructor
// */
// GameLib.D3.PhysicsWorld.prototype.generateTriangleMeshShapeDivided = function(
// graphics,
// graphicsMesh,
// mass,
// friction,
// createCollisionSubMeshes,
// facesPerSubsection,
// subsectionsToMerge
// ) {
// graphics.isNotThreeThrow();
// this.engine.isNotCannonThrow();
//
// if(mass == null || typeof mass == 'undefined') {
// mass = 0;
// }
//
// if(friction == null || typeof friction == 'undefined') {
// friction = 10;
// }
//
// if(createCollisionSubMeshes == null || typeof createCollisionSubMeshes == 'undefined') {
// createCollisionSubMeshes = false;
// }
//
// var processedFaces = 0;
// var facesPerSubSection = facesPerSubsection || 0;
// var subMeshesToMerge = subsectionsToMerge || 0;
// var totalAmtFaces = graphicsMesh.geometry.faces.length;
// var facesToProcess = createCollisionSubMeshes ? (subMeshesToMerge * facesPerSubSection) : totalAmtFaces;
//
// var pairs = []; // output
//
// var vertices = [];
// var indicies = [];
//
// for(var i = 0; i <= totalAmtFaces; i++) {
// if(processedFaces == facesToProcess || i == totalAmtFaces) {
//
// var body = null;
//
// var meshShape = new this.engine.instance.Trimesh(vertices, indicies);
//
// meshShape.setScale(new this.engine.instance.Vec3(
// graphicsMesh.scale.x,
// graphicsMesh.scale.y,
// graphicsMesh.scale.z
// ));
//
// meshShape.updateAABB();
// meshShape.updateNormals();
// meshShape.updateEdges();
// meshShape.updateBoundingSphereRadius();
// meshShape.updateTree();
//
// body = new this.engine.instance.Body({
// mass: mass,
// friction: friction
// });
// body.addShape(meshShape);
//
// pairs.push({
// threeObject : createCollisionSubMeshes ? null : graphicsMesh,
// physicsObject : body
// });
//
// vertices = [];
// indicies = [];
// processedFaces = 0;
//
// if(i == totalAmtFaces) {
// return pairs;
// }
// }
//
// var face = graphicsMesh.geometry.faces[i];
// indicies.push(indicies.length);
// indicies.push(indicies.length);
// indicies.push(indicies.length);
//
// var v0 = graphicsMesh.geometry.vertices[face.a];
// var v1 = graphicsMesh.geometry.vertices[face.b];
// var v2 = graphicsMesh.geometry.vertices[face.c];
//
// vertices.push(v0.x, v0.y, v0.z);
// vertices.push(v1.x, v1.y, v1.z);
// vertices.push(v2.x, v2.y, v2.z);
//
// processedFaces++;
// }
// };
//
// GameLib.D3.PhysicsWorld.prototype.generateConvexPolyShape = function(
// graphics,
// mesh
// ) {
// var processedFaces = 0;
// var facesPerSubSection = 2; // *2 -> SUBDIVISION MESH
// var subMeshesToMerge = 4; // *2 -> SUBDIVISION MESH
// var facesToProcess = subMeshesToMerge * facesPerSubSection;
//
// var vertices = [];
// var indicies = [];
//
// for(var i = 0; i <= mesh.geometry.faces.length; i++) {
// if(processedFaces == facesToProcess || i == mesh.geometry.faces.length) {
//
// // try and create convex poly...........
// var convexIndices = [];
// for(var index = 0; index < indicies.length / 3; index++) {
// convexIndices.push([ indicies[index * 3], indicies[index * 3 + 1], indicies[index * 3 + 2] ]);
// }
//
// var convexVertices = [];
// for(var vert = 0; vert < vertices.length / 3; vert++) {
// convexVertices[vert] = new CANNON.Vec3(vertices[vert * 3] * mesh.scale.x, vertices[vert * 3 + 1] * mesh.scale.y, vertices[vert * 3 + 2] * mesh.scale.z);
// }
//
// var meshShape = new GameLib.D3.Shape(this.engine, GameLib.D3.Shape.SHAPE_TYPE_CONVEX_HULL, {x:1,y:1,z:1},convexVertices, convexIndices);
//
// var body = new GameLib.D3.RigidBody(this.engine, 0, 1);
// body.addShape(meshShape);
//
// this.addRigidBody(body);
//
// vertices = [];
// indicies = [];
// processedFaces = 0;
//
// console.log("SPLIT MESH TO CONVEX POLY");
//
// if(i == mesh.geometry.faces.length) {
// break;
// }
// }
//
// var face = mesh.geometry.faces[i];
// indicies.push(indicies.length);
// indicies.push(indicies.length);
// indicies.push(indicies.length);
//
// var v0 = mesh.geometry.vertices[face.a];
// var v1 = mesh.geometry.vertices[face.b];
// var v2 = mesh.geometry.vertices[face.c];
//
// vertices.push(v0.x, v0.y, v0.z);
// vertices.push(v1.x, v1.y, v1.z);
// vertices.push(v2.x, v2.y, v2.z);
//
// processedFaces++;
// }
//
// };
//
// /**
// * @param graphics GameLib.D3.Graphics
// * @param graphicsMesh THREE.Mesh
// * @returns {GameLib.D3.Shape}
// * @constructor
// */
// GameLib.D3.PhysicsWorld.prototype.generateTriangleMeshShape = function(
// graphics,
// graphicsMesh
// ) {
//
// // - - - - - - - - - - - - - - - - - - - - - - - - -
// // Note: I did not test this yet with the API data.
// // - - - - - - - - - - - - - - - - - - - - - - - - -
//
// var scaledVertices = [];
// for(var i = 0, l = graphicsMesh.geometry.vertices.length; i < l; i++) {
//
// var vertex = graphicsMesh.geometry.vertices[i];
//
// scaledVertices.push(new this.engine.instance.Vec3(
// vertex.x * graphicsMesh.scale.x,
// vertex.y * graphicsMesh.scale.y,
// vertex.z * graphicsMesh.scale.z
// ));
// }
//
// var triangleFaces = [];
// for(var f = 0, fl = graphicsMesh.geometry.faces.length; f < fl; f++) {
// var i0 = graphicsMesh.geometry.faces[f].a;
// var i1 = graphicsMesh.geometry.faces[f].b;
// var i2 = graphicsMesh.geometry.faces[f].c;
//
// triangleFaces.push([
// i0, i1, i2
// ]);
// }
//
// // - - - - - - - - - - - - - - - - - - -
// // Create collision mesh
// // - - - - - - - - - - - - - - - - - - -
//
// var reindexedFaces = {};
// var vertices = [];
// var faces = [];
//
// var processedFaces = 0;
// var totalFacesToProcess = triangleFaces.length;
// var flLastIndex = 0;
//
// for(var f = 0; f < totalFacesToProcess; f++) {
//
// var i0 = triangleFaces[f][0];
// var i1 = triangleFaces[f][1];
// var i2 = triangleFaces[f][2];
//
// if(typeof reindexedFaces[i0] === 'undefined') {
// vertices.push(scaledVertices[i0].x, scaledVertices[i0].y, scaledVertices[i0].z);
// reindexedFaces[i0] = flLastIndex;
// flLastIndex++;
// }
//
// if(typeof reindexedFaces[i1] === 'undefined') {
// vertices.push(scaledVertices[i1].x, scaledVertices[i1].y, scaledVertices[i1].z);
// reindexedFaces[i1] = flLastIndex;
// flLastIndex++;
// }
//
// if(typeof reindexedFaces[i2] === 'undefined') {
// vertices.push(scaledVertices[i2].x, scaledVertices[i2].y, scaledVertices[i2].z);
// reindexedFaces[i2] = flLastIndex;
// flLastIndex++;
// }
//
// faces.push(reindexedFaces[i0], reindexedFaces[i1], reindexedFaces[i2]);
//
// processedFaces++;
// }
//
// return new GameLib.D3.Shape(this.engine, GameLib.D3.Shape.SHAPE_TYPE_TRIMESH, {x : 1, y : 1, z : 1}, vertices, faces);
// };
//
// /**
// * @param triangleMeshBody GameLib.D3.RigidBody
// * @param rayscale Number
// * @param maxTriangleDistance Number
// * @param createCompoundShape Boolean
// * @param graphics GameLib.D3.Graphics
// * @param triangleMeshShapes GameLib.D3.Shape[]
// * @param createDebugView Boolean
// * @returns {GameLib.D3.RigidBody}
// * @constructor
// */
// GameLib.D3.PhysicsWorld.prototype.fixupTriangleMeshShape = function(
// triangleMeshBody,
// triangleMeshShapes,
// rayscale,
// maxTriangleDistance,
// createCompoundShape,
// graphics,
// createDebugView
// ) {
// this.engine.isNotCannonThrow();
//
// graphics.isNotThreeThrow();
//
// if(rayscale == null || typeof rayscale == 'undefined' || rayscale == 0) {
// rayscale = 10;
// }
//
// if(maxTriangleDistance == null || typeof maxTriangleDistance == 'undefined') {
// maxTriangleDistance = 13;
// }
//
// var world = this.instance;
//
// var raycastResult = new this.engine.instance.RaycastResult();
//
// var brokenFaceIndicators = [];
//
// var totalFaces = 0;
// var totalBrokenFaces = 0;
// var totalFixedFaces = 0;
// var fixedTriangleMeshObjects = [];
//
// for(var i in triangleMeshShapes) {
// var trimesh = triangleMeshShapes[i].instance;
//
// var brokenFaces = [];
// totalFaces += (trimesh.indices.length / 3);
//
// for(var face = 0; face < trimesh.indices.length / 3; face++) {
//
// var i0 = trimesh.indices[face * 3];
// var i1 = trimesh.indices[face * 3 + 1];
// var i2 = trimesh.indices[face * 3 + 2];
//
// var triangleCenterPoint = new graphics.instance.Vector3()
// .add(new graphics.instance.Vector3(
// trimesh.vertices[i0 * 3],
// trimesh.vertices[i0 * 3 + 1],
// trimesh.vertices[i0 * 3 + 2])
// )
// .add(new graphics.instance.Vector3(
// trimesh.vertices[i1 * 3],
// trimesh.vertices[i1 * 3 + 1],
// trimesh.vertices[i1 * 3 + 2])
// )
// .add(new graphics.instance.Vector3(
// trimesh.vertices[i2 * 3],
// trimesh.vertices[i2 * 3 + 1],
// trimesh.vertices[i2 * 3 + 2])
// )
// .divideScalar(3);
//
// var triangleNormal = new this.engine.instance.Vec3();
// trimesh.getNormal(face , triangleNormal);
//
// var from = new this.engine.instance.Vec3(
// triangleCenterPoint.x + triangleNormal.x,
// triangleCenterPoint.y + triangleNormal.y,
// triangleCenterPoint.z + triangleNormal.z
// );
//
// var to = new this.engine.instance.Vec3(
// from.x - triangleNormal.x * rayscale,
// from.y - triangleNormal.y * rayscale,
// from.z - triangleNormal.z * rayscale
// );
//
// world.raycastClosest(from, to, {}, raycastResult);
//
// // visualize results
// if(createDebugView){
// var graphicsGeometry = new graphics.instance.Geometry();
// var wireframeMesh = new graphics.instance.Mesh(
// graphicsGeometry,
// new graphics.instance.MeshBasicMaterial({
// color: 0xff0000,
// wireframe: true,
// opacity: 1
// })
// );
//
// var arrow = new graphics.instance.ArrowHelper(
// new graphics.instance.Vector3(
// triangleNormal.x,
// triangleNormal.y,
// triangleNormal.z
// ).normalize(),
//
// new graphics.instance.Vector3(
// from.x,
// from.y,
// from.z
// ),
//
// rayscale / 2,
// raycastResult.hasHit ? new graphics.instance.Color(0, 1, 0)
// : new graphics.instance.Color(1, 0, 0)
// );
//
// wireframeMesh.add( arrow );
// brokenFaceIndicators.push(wireframeMesh);
// }
//
// if(!raycastResult.hasHit) {
// brokenFaces.push({
// faceIndex : face,
//
// vertices : [
// new this.engine.instance.Vec3(
// trimesh.vertices[i0 * 3],
// trimesh.vertices[i0 * 3 + 1],
// trimesh.vertices[i0 * 3 + 2]
// ),
//
// new this.engine.instance.Vec3(
// trimesh.vertices[i1 * 3],
// trimesh.vertices[i1 * 3 + 1],
// trimesh.vertices[i1 * 3 + 2]
// ),
//
// new this.engine.instance.Vec3(
// trimesh.vertices[i2 * 3],
// trimesh.vertices[i2 * 3 + 1],
// trimesh.vertices[i2 * 3 + 2]
// )
// ],
//
// center : triangleCenterPoint,
//
// parent : trimesh
// });
// }
// }
//
// // fix up broken faces
//
// var bFaceIndexed = {};
// for(var b = 0; b < brokenFaces.length; b++) {
// var brokenFace = brokenFaces[b];
//
// if(brokenFace.marked) {
// continue;
// }
//
// bFaceIndexed[b] = {
// indices : [],
// vertices : []
// };
//
// var indicesAmount = bFaceIndexed[b].indices.length;
//
// // add the current broken face itself to the array
// bFaceIndexed[b].indices.push(
// indicesAmount,
// indicesAmount + 1,
// indicesAmount + 2
// );
//
// bFaceIndexed[b].vertices.push(
// brokenFace.vertices[0].x,
// brokenFace.vertices[0].y,
// brokenFace.vertices[0].z
// );
//
// bFaceIndexed[b].vertices.push(
// brokenFace.vertices[1].x,
// brokenFace.vertices[1].y,
// brokenFace.vertices[1].z
// );
//
// bFaceIndexed[b].vertices.push(
// brokenFace.vertices[2].x,
// brokenFace.vertices[2].y,
// brokenFace.vertices[2].z
// );
//
// for(var bb = 0; bb < brokenFaces.length; bb++) {
//
// if(bb == b) {
// continue;
// }
//
// var otherBrokenFace = brokenFaces[bb];
//
// if(otherBrokenFace.marked) {
// continue;
// }
//
// if(brokenFace.center.distanceTo(otherBrokenFace.center) <= maxTriangleDistance) {
// var indicesAmount = bFaceIndexed[b].indices.length;
//
// bFaceIndexed[b].indices.push(
// indicesAmount,
// indicesAmount + 1,
// indicesAmount + 2
// );
//
// bFaceIndexed[b].vertices.push(
// otherBrokenFace.vertices[0].x,
// otherBrokenFace.vertices[0].y,
// otherBrokenFace.vertices[0].z
// );
//
// bFaceIndexed[b].vertices.push(
// otherBrokenFace.vertices[1].x,
// otherBrokenFace.vertices[1].y,
// otherBrokenFace.vertices[1].z
// );
//
// bFaceIndexed[b].vertices.push(
// otherBrokenFace.vertices[2].x,
// otherBrokenFace.vertices[2].y,
// otherBrokenFace.vertices[2].z
// );
//
// otherBrokenFace.marked = true;
// }
// }
// }
//
//
// // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// // Decide if we want to create new rigiwyd bodies, or create a compound mesh
// // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// for(var e in bFaceIndexed) {
// var element = bFaceIndexed[e];
//
// var shape = new GameLib.D3.Shape(this.engine, GameLib.D3.Shape.SHAPE_TYPE_TRIMESH, { x : 1, y : 1, z : 1 }, element.vertices, element.indices);
//
// if(createCompoundShape) {
// triangleMeshBody.addShape(shape);
// } else {
//
// var body = new GameLib.D3.RigidBody(this.engine, 0, 12);
//
// //TODO: this is just a hack.
// body.instance.collisionFilterGroup = 1 | 2; // puts this body in two groups.
//
// body.addShape(shape);
// this.addRigidBody(body);
// }
//
// fixedTriangleMeshObjects.push(shape);
// totalFixedFaces += element.indices.length / 3;
// }
//
// // TODO: remove duplicate indices
// /*trimesh.updateNormals();
// trimesh.updateEdges();
// trimesh.updateTree();
// trimesh.updateAABB();
// trimesh.updateBoundingSphereRadius();*/
//
// // map faceIndex to flat face index (faceIndex * 3) +0, 1, 2 -> triangle indices
// console.log("i = " + i, brokenFaces);
// totalBrokenFaces += brokenFaces.length;
// }
//
// console.log("total faces", totalFaces);
// console.log("total broken faces", totalBrokenFaces);
// console.log("broken faces in percent", (totalBrokenFaces / totalFaces) * 100);
// console.log("total fixed faces", totalFixedFaces);
// console.log("fixed triangle mesh shapes", fixedTriangleMeshObjects.length);
//
// return {
// brokenFaceIndicators : brokenFaceIndicators,
// fixedTriangleMeshShapes : fixedTriangleMeshObjects
// };
// };
/**
* Physics
* @param id
* @param name
* @param physicsType
* @constructor
*/
GameLib.D3.Physics = function Physics(
id,
name,
physicsType
) {
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Physics (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(physicsType)) {
physicsType = GameLib.D3.Physics.PHYSICS_TYPE_CANNON;
}
this.physicsType = physicsType;
this.createInstance();
};
/**
* GameLib.D3.Physics Types
* @type {number}
*/
GameLib.D3.Physics.PHYSICS_TYPE_CANNON = 0x1;
/**
* @returns {THREE.Physics}
*/
GameLib.D3.Physics.prototype.createInstance = function() {
this.instance = CANNON;
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Physics.prototype.updateInstance = function() {
};
/**
* Logs a warning and throws an error if not cannon
*/
GameLib.D3.Physics.prototype.isNotCannonThrow = function() {
if (this.physicsType !== GameLib.D3.Physics.PHYSICS_TYPE_CANNON) {
console.warn('Only CANNON supported for this function');
throw new Error('Only CANNON supported for this function');
}
};
/**
* Contains a Poly vertex data structure
* @param localIndex
* @param mvertIndex
* @param uv GameLib.API.Vector2
* @param materialIndex
* @param edgeIndex
* @constructor
*/
GameLib.D3.PolyVertex = function(
localIndex,
mvertIndex,
uv,
materialIndex,
edgeIndex
) {
this.localIndex = localIndex;
this.mvertIndex = mvertIndex;
this.uv = uv;
this.materialIndex = materialIndex;
this.edgeIndex = edgeIndex;
};
/**
* Clone a PolyVertex
* @returns {GameLib.D3.PolyVertex}
*/
GameLib.D3.PolyVertex.prototype.clone = function() {
return new GameLib.D3.PolyVertex(
this.localIndex,
this.mvertIndex,
this.uv.copy(),
this.materialIndex,
this.edgeIndex
)
};
/**
* RaycastVehicle Runtime
* @param physics GameLib.D3.Graphics
* @param apiRaycastVehicle GameLib.D3.API.RaycastVehicle
* @constructor
*/
GameLib.D3.RaycastVehicle = function (
physics,
apiRaycastVehicle
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiRaycastVehicle)) {
apiRaycastVehicle = {};
}
if (apiRaycastVehicle instanceof GameLib.D3.RaycastVehicle) {
return apiRaycastVehicle;
}
GameLib.D3.API.RaycastVehicle.call(
this,
apiRaycastVehicle.id,
apiRaycastVehicle.name,
apiRaycastVehicle.chassis,
apiRaycastVehicle.wheels,
apiRaycastVehicle.raycastWheels,
apiRaycastVehicle.parentWorld,
apiRaycastVehicle.parentEntity
);
if (this.chassis instanceof GameLib.D3.API.RaycastVehicle) {
this.chassis = new GameLib.D3.RaycastVehicle(
this.physics,
this.chassis
)
}
this.wheels = this.wheels.map(function(wheel){
if (wheel instanceof GameLib.D3.API.RigidBody) {
return new GameLib.D3.RigidBody(
this.physics,
wheel
)
} else {
return wheel;
}
}.bind(this));
this.raycastWheels = this.raycastWheels.map(function(raycastWheel){
if (raycastWheel instanceof GameLib.D3.API.RaycastWheel) {
return new GameLib.D3.RaycastWheel(
this.physics,
raycastWheel
)
} else {
return raycastWheel;
}
}.bind(this));
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_RAYCAST_VEHICLE,
{
'chassis' : GameLib.D3.RigidBody,
'wheels' : [GameLib.D3.RigidBody],
'raycastWheels' : [GameLib.D3.RaycastWheel],
'parentWorld' : GameLib.D3.PhysicsWorld
}
);
};
GameLib.D3.RaycastVehicle.prototype = Object.create(GameLib.D3.API.RaycastVehicle.prototype);
GameLib.D3.RaycastVehicle.prototype.constructor = GameLib.D3.RaycastVehicle;
/**
*
* @returns {*}
*/
GameLib.D3.RaycastVehicle.prototype.createInstance = function() {
/**
* At this point - even though this component exists - the chassis could maybe not been have assigned, failed to
* register as a dependency, and therefore is not present at the time of createInstance() - we will need to call
* delayedInstance somehow...
* @type {GameLib.D3.RaycastVehicle|GameLib.D3.API.RaycastVehicle|*}
*/
if (GameLib.Utils.UndefinedOrNull(this.chassis)) {
throw new Error('no chassis');
}
if (GameLib.Utils.UndefinedOrNull(this.chassis.instance)) {
throw new Error('no chassis instance');
}
if (GameLib.Utils.UndefinedOrNull(this.parentWorld)) {
throw new Error('no parent world');
}
if (GameLib.Utils.UndefinedOrNull(this.parentWorld.instance)) {
throw new Error('no parent world instance');
}
this.instance = new CANNON.RaycastVehicle({
chassisBody: this.chassis.instance
});
this.raycastWheels.map(
function(wheel){
if (GameLib.Utils.UndefinedOrNull(wheel)) {
throw new Error('no wheel');
}
if (GameLib.Utils.UndefinedOrNull(wheel.instance)) {
throw new Error('no wheel instance');
}
this.instance.addWheel(wheel.instance);
}.bind(this)
);
this.instance.addToWorld(this.parentWorld.instance);
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.RaycastVehicle.prototype.updateInstance = function() {
// this.instance.chassisBody = this.chassis.instance;
//TODO: add / remove wheels?
console.log('TODO: update raycast vehicle instance');
};
/**
* GameLib.D3.RaycastVehicle to GameLib.D3.API.RaycastVehicle
* @returns {GameLib.D3.API.RaycastVehicle}
*/
GameLib.D3.RaycastVehicle.prototype.toApiObject = function() {
var apiRaycastVehicle = new GameLib.D3.API.RaycastVehicle(
this.id,
this.name,
GameLib.Utils.IdOrNull(this.chassis),
this.wheels.map(function(wheel){
return GameLib.Utils.IdOrNull(wheel);
}),
this.raycastWheels.map(function(raycastWheel){
return GameLib.Utils.IdOrNull(raycastWheel);
}),
GameLib.Utils.IdOrNull(this.parentWorld),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiRaycastVehicle;
};
/**
* GameLib.D3.RaycastVehicle from Object RaycastVehicle
* @param physics
* @param objectComponent
* @returns {GameLib.D3.RaycastVehicle}
* @constructor
*/
GameLib.D3.RaycastVehicle.FromObject = function(physics, objectComponent) {
var apiRaycastVehicle = GameLib.D3.API.RaycastVehicle.FromObject(objectComponent);
return new GameLib.D3.RaycastVehicle(
physics,
apiRaycastVehicle
);
};
/**
* RaycastWheel Runtime
* @param physics GameLib.D3.Graphics
* @param apiRaycastWheel GameLib.D3.API.RaycastWheel
* @constructor
*/
GameLib.D3.RaycastWheel = function (
physics,
apiRaycastWheel
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiRaycastWheel)) {
apiRaycastWheel = {};
}
if (apiRaycastWheel instanceof GameLib.D3.RaycastWheel) {
return apiRaycastWheel;
}
GameLib.D3.API.RaycastWheel.call(
this,
apiRaycastWheel.id,
apiRaycastWheel.name,
apiRaycastWheel.radius,
apiRaycastWheel.directionLocal,
apiRaycastWheel.suspensionStiffness,
apiRaycastWheel.suspensionRestLength,
apiRaycastWheel.frictionSlip,
apiRaycastWheel.dampingRelaxation,
apiRaycastWheel.dampingCompression,
apiRaycastWheel.maxSuspensionForce,
apiRaycastWheel.rollInfluence,
apiRaycastWheel.axleLocal,
apiRaycastWheel.chassisConnectionPointLocal,
apiRaycastWheel.maxSuspensionTravel,
apiRaycastWheel.customSlidingRotationalSpeed,
apiRaycastWheel.useCustomSlidingRotationalSpeed,
apiRaycastWheel.parentEntity,
apiRaycastWheel.parentMesh
);
this.directionLocal = new GameLib.Vector3(
this.physics,
this.directionLocal,
this
);
this.axleLocal = new GameLib.Vector3(
this.physics,
this.axleLocal,
this
);
this.chassisConnectionPointLocal = new GameLib.Vector3(
this.physics,
this.chassisConnectionPointLocal,
this
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_RAYCAST_WHEEL,
{
'parentMesh' : GameLib.D3.Mesh
}
);
};
GameLib.D3.RaycastWheel.prototype = Object.create(GameLib.D3.API.RaycastWheel.prototype);
GameLib.D3.RaycastWheel.prototype.constructor = GameLib.D3.RaycastWheel;
/**
*
* @returns {*}
*/
GameLib.D3.RaycastWheel.prototype.createInstance = function() {
this.instance = {
radius: this.radius,
directionLocal: this.directionLocal.instance,
suspensionStiffness: this.suspensionStiffness,
suspensionRestLength: this.suspensionRestLength,
frictionSlip: this.frictionSlip,
dampingRelaxation: this.dampingRelaxation,
dampingCompression: this.dampingCompression,
maxSuspensionForce: this.maxSuspensionForce,
rollInfluence: this.rollInfluence,
axleLocal: this.axleLocal.instance,
chassisConnectionPointLocal: this.chassisConnectionPointLocal.instance,
maxSuspensionTravel: this.maxSuspensionTravel,
customSlidingRotationalSpeed: this.customSlidingRotationalSpeed,
useCustomSlidingRotationalSpeed: this.useCustomSlidingRotationalSpeed
};
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.RaycastWheel.prototype.updateInstance = function() {
this.instance.radius = this.radius;
this.instance.directionLocal = this.directionLocal.instance;
this.instance.suspensionStiffness = this.suspensionStiffness;
this.instance.suspensionRestLength = this.suspensionRestLength;
this.instance.frictionSlip = this.frictionSlip;
this.instance.dampingRelaxation = this.dampingRelaxation;
this.instance.dampingCompression = this.dampingCompression;
this.instance.maxSuspensionForce = this.maxSuspensionForce;
this.instance.rollInfluence = this.rollInfluence;
this.instance.axleLocal = this.axleLocal.instance;
this.instance.chassisConnectionPointLocal = this.chassisConnectionPointLocal.instance;
this.instance.maxSuspensionTravel = this.maxSuspensionTravel;
this.instance.customSlidingRotationalSpeed = this.customSlidingRotationalSpeed;
this.instance.useCustomSlidingRotationalSpeed = this.useCustomSlidingRotationalSpeed;
};
/**
* GameLib.D3.RaycastWheel to GameLib.D3.API.RaycastWheel
* @returns {GameLib.D3.API.RaycastWheel}
*/
GameLib.D3.RaycastWheel.prototype.toApiObject = function() {
var apiRaycastWheel = new GameLib.D3.API.RaycastWheel(
this.id,
this.name,
this.radius,
this.directionLocal.toApiObject(),
this.suspensionStiffness,
this.suspensionRestLength,
this.frictionSlip,
this.dampingRelaxation,
this.dampingCompression,
this.maxSuspensionForce,
this.rollInfluence,
this.axleLocal.toApiObject(),
this.chassisConnectionPointLocal.toApiObject(),
this.maxSuspensionTravel,
this.customSlidingRotationalSpeed,
this.useCustomSlidingRotationalSpeed,
GameLib.Utils.IdOrNull(this.parentEntity),
GameLib.Utils.IdOrNull(this.parentMesh)
);
return apiRaycastWheel;
};
/**
* GameLib.D3.RaycastWheel from Object RaycastWheel
* @param physics
* @param objectComponent
* @returns {GameLib.D3.RaycastWheel}
* @constructor
*/
GameLib.D3.RaycastWheel.FromObject = function(physics, objectComponent) {
var apiRaycastWheel = GameLib.D3.API.RaycastWheel.FromObject(objectComponent);
return new GameLib.D3.RaycastWheel(
physics,
apiRaycastWheel
);
};
GameLib.D3.RaycastWheel.prototype.setChassisLocalConnectionPoint = function() {
if (!this.parentMesh) {
console.log('you need to set the parent mesh first');
}
this.chassisConnectionPointLocal.x = this.parentMesh.position.x;
this.chassisConnectionPointLocal.y = this.parentMesh.position.y;
this.chassisConnectionPointLocal.z = this.parentMesh.position.z;
};
/**
* Raycaster for GameLib.D3
* @param graphics GameLib.D3.Graphics
* @param apiRaycaster
* @constructor
*/
GameLib.D3.Raycaster = function(
graphics,
apiRaycaster
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiRaycaster)) {
apiRaycaster = {};
}
if (apiRaycaster instanceof GameLib.D3.Raycaster) {
return apiRaycaster;
}
GameLib.D3.API.Raycaster.call(
this,
apiRaycaster.id,
apiRaycaster.name,
apiRaycaster.position,
apiRaycaster.direction
);
this.position = new GameLib.Vector3(
this.graphics,
this.position,
this
);
this.direction = new GameLib.Vector3(
this.graphics,
this.direction,
this
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_RAYCASTER
);
};
GameLib.D3.Raycaster.prototype = Object.create(GameLib.D3.API.Raycaster.prototype);
GameLib.D3.Raycaster.prototype.constructor = GameLib.D3.Raycaster;
/**
* Creates or updates a raycaster instance
*/
GameLib.D3.Raycaster.prototype.createInstance = function() {
this.instance = new THREE.Raycaster();
this.instance.set(
this.position.instance,
this.direction.instance
);
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.Raycaster.prototype.updateInstance = function() {
this.position.instance.x = this.position.x;
this.position.instance.y = this.position.y;
this.position.instance.z = this.position.z;
this.direction.instance.x = this.direction.x;
this.direction.instance.y = this.direction.y;
this.direction.instance.z = this.direction.z;
this.instance.set(
this.position.instance,
this.direction.instance
);
};
GameLib.D3.Raycaster.prototype.toApiObject = function() {
return new GameLib.D3.API.Raycaster(
this.id,
this.name,
this.position.toApiObject(),
this.direction.toApiObject()
)
};
GameLib.D3.Raycaster.FromObject = function(graphics, objectRaycaster) {
var apiRaycaster = GameLib.D3.API.Raycaster.FromObject(objectRaycaster);
var raycaster = new GameLib.D3.Raycaster(
graphics,
apiRaycaster
);
return raycaster;
};
/**
* Sets the direction and position of this raycaster
* @param position GameLib.Vector3
* @param direction GameLib.Vector3
*/
GameLib.D3.Raycaster.prototype.set = function(
position,
direction
) {
this.position.x = position.x;
this.position.y = position.y;
this.position.z = position.z;
this.direction.x = direction.x;
this.direction.y = direction.y;
this.direction.z = direction.z;
this.position.updateInstance();
this.direction.updateInstance();
};
/**
* Sets the direction of this raycaster
* @param direction GameLib.Vector3
*/
GameLib.D3.Raycaster.prototype.setDirection = function(
direction
) {
this.direction.x = direction.x;
this.direction.y = direction.y;
this.direction.z = direction.z;
this.direction.updateInstance();
};
/**
* Sets the position of this raycaster
* @param position GameLib.Vector3
*/
GameLib.D3.Raycaster.prototype.setPosition = function(
position
) {
this.position.x = position.x;
this.position.y = position.y;
this.position.z = position.z;
this.position.updateInstance();
};
/**
* Sets the ray position and direction from the mouse coordinates (in proper x and y (-1 to 1))
* @param mouse
* @param camera
*/
GameLib.D3.Raycaster.prototype.setFromCamera = function(
mouse,
camera
) {
this.instance.setFromCamera(
mouse,
camera.instance
);
this.position.x = this.instance.ray.origin.x;
this.position.y = this.instance.ray.origin.y;
this.position.z = this.instance.ray.origin.z;
this.direction.x = this.instance.ray.direction.x;
this.direction.y = this.instance.ray.direction.y;
this.direction.z = this.instance.ray.direction.z;
};
/**
* Gets all interesected GameLib.D3.Mesh objects
* @param meshes [GameLib.D3.Mesh]
*/
GameLib.D3.Raycaster.prototype.getIntersectedObjects = function(meshes) {
return meshes.reduce(
function (result, mesh) {
var intersects = this.instance.intersectObject(mesh.instance);
if (intersects.length > 0) {
result.push(
{
mesh: mesh,
distance : intersects[0].distance
}
);
}
return result;
}.bind(this),
[]
);
// var intersects = this.instance.intersectObjects(meshInstances);
//
// return intersects.reduce(
//
// function (result, intersect) {
//
// meshes.map(
// function(mesh){
// if (mesh.instance === intersect.object){
// result.push(
// {
// mesh : mesh,
// distance : intersect.distance
// }
// );
// }
// }
// );
//
// return result;
// },
// []
// );
};
/**
* Returns the face normal (if any) of an intersection between current ray position, direction and a provided mesh
* @param mesh GameLib.D3.Mesh
* @returns {null | GameLib.Vector3}
*/
GameLib.D3.Raycaster.prototype.getFaceNormal = function(mesh) {
var normal = null;
var intersect = this.instance.intersectObject(
mesh.instance
);
if (intersect && intersect.length > 0) {
normal = new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(
intersect[0].face.normal.x,
intersect[0].face.normal.y,
intersect[0].face.normal.z
),
this
);
}
return normal;
};
/**
* Returns the face normal (if any) of an intersection between current ray position, direction and a provided mesh
* @param mesh GameLib.D3.Mesh
* @returns {null | GameLib.Vector3}
*/
GameLib.D3.Raycaster.prototype.getIntersectPoint = function(mesh) {
var point = null;
var intersect = this.instance.intersectObject(
mesh.instance
);
if (intersect && intersect.length > 0) {
point = new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(
intersect[0].point.x,
intersect[0].point.y,
intersect[0].point.z
),
this
);
}
return point;
};
/**
* Renders a scene with a camera
* @param graphics GameLib.D3.Graphics
* @param apiRenderTarget GameLib.D3.API.RenderTarget
* @constructor
*/
GameLib.D3.RenderTarget = function (
graphics,
apiRenderTarget
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiRenderTarget)) {
apiRenderTarget = {};
}
if (apiRenderTarget instanceof GameLib.D3.RenderTarget) {
return apiRenderTarget;
}
GameLib.D3.API.RenderTarget.call(
this,
apiRenderTarget.id,
apiRenderTarget.name,
apiRenderTarget.width,
apiRenderTarget.height,
apiRenderTarget.stencilBuffer,
apiRenderTarget.texture
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_RENDER_TARGET,
{
'texture' : GameLib.D3.Texture
}
);
};
GameLib.D3.RenderTarget.prototype = Object.create(GameLib.D3.API.RenderTarget.prototype);
GameLib.D3.RenderTarget.prototype.constructor = GameLib.D3.RenderTarget;
/**
* Creates a Render Target instance
* @returns {*}
*/
GameLib.D3.RenderTarget.prototype.createInstance = function() {
if (GameLib.Utils.UndefinedOrNull(this.texture)) {
throw new Error('no texture');
}
if (GameLib.Utils.UndefinedOrNull(this.texture.instance)) {
throw new Error('no texture instance');
}
this.instance = new THREE.WebGLRenderTarget(
this.width,
this.height,
{
stencilBuffer : this.stencilBuffer
}
);
this.instance.texture = this.texture.instance;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* updates instance
*/
GameLib.D3.RenderTarget.prototype.updateInstance = function() {
if (this.instance) {
this.instance.setSize(this.width, this.height);
this.instance.stencilBuffer = this.stencilBuffer;
if (this.texture && this.texture.instance) {
this.instance.texture = this.texture.instance;
this.instance.texture.needsUpdate = true;
} else {
this.instance.texture = null;
}
} else {
try {
this.createInstance();
} catch (error) {
console.error(error);
}
}
};
/**
* Render Target to API Render Target
* @returns {GameLib.D3.API.RenderTarget}
*/
GameLib.D3.RenderTarget.prototype.toApiObject = function() {
var apiRenderTarget = new GameLib.D3.API.RenderTarget(
this.id,
this.name,
this.width,
this.height,
this.stencilBuffer,
GameLib.Utils.IdOrNull(this.texture),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiRenderTarget;
};
/**
*
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.RenderTarget}
* @constructor
*/
GameLib.D3.RenderTarget.FromObject = function(graphics, objectComponent) {
var apiRenderTarget = GameLib.D3.API.RenderTarget.FromObject(objectComponent);
return new GameLib.D3.RenderTarget(
graphics,
apiRenderTarget
);
};
/**
* Renders a scene with a camera
* @param graphics GameLib.D3.Graphics
* @param apiRenderer GameLib.D3.API.Renderer
* @constructor
*/
GameLib.D3.Renderer = function (
graphics,
apiRenderer
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiRenderer)) {
apiRenderer = {};
}
if (apiRenderer instanceof GameLib.D3.Renderer) {
return apiRenderer;
}
GameLib.D3.API.Renderer.call(
this,
apiRenderer.id,
apiRenderer.name,
apiRenderer.autoClear,
apiRenderer.localClipping,
apiRenderer.width,
apiRenderer.height,
apiRenderer.preserveDrawingBuffer,
apiRenderer.domElement,
apiRenderer.clearColor,
apiRenderer.camera,
apiRenderer.scenes,
apiRenderer.viewports,
apiRenderer.clippingPlanes,
apiRenderer.bufferScene,
apiRenderer.bufferCamera,
apiRenderer.renderTarget,
apiRenderer.defaultScene,
apiRenderer.sortObjects,
apiRenderer.parentEntity
);
this.clearColor = new GameLib.Color(
this.graphics,
this.clearColor,
this
);
if (this.domElement instanceof GameLib.API.DomElement) {
this.domElement = new GameLib.DomElement(
this.domElement
);
}
if (this.camera instanceof GameLib.D3.API.Camera) {
this.camera = new GameLib.D3.Camera(
this.graphics,
this.camera
)
}
this.scenes = this.scenes.map(function(scene){
if (scene instanceof GameLib.D3.API.Scene) {
return new GameLib.D3.Scene(
this.graphics,
scene
);
} else {
return scene;
}
}.bind(this));
this.viewports = this.viewports.map(function(viewport){
if (viewport instanceof GameLib.D3.API.Viewport) {
return new GameLib.D3.Viewport(
this.graphics,
viewport
);
} else {
return viewport;
}
}.bind(this));
this.clippingPlanes = this.clippingPlanes.map(function(clippingPlane){
if (clippingPlane instanceof GameLib.D3.API.Mesh) {
return new GameLib.D3.Mesh.Plane(
this.graphics,
clippingPlane,
clippingPlane.width,
clippingPlane.height,
clippingPlane.widthSegments,
clippingPlane.heightSegments,
clippingPlane.heightMapScale,
clippingPlane.isHeightMap,
clippingPlane.isClippingPlane,
clippingPlane.distanceFromOrigin
);
} else {
return clippingPlane;
}
}.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
)
}
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_RENDERER,
{
'domElement' : GameLib.DomElement,
'camera' : GameLib.D3.Camera,
'scenes' : [GameLib.D3.Scene],
'viewports' : [GameLib.D3.Viewport],
'clippingPlanes': [GameLib.D3.Mesh.Plane],
'bufferScene' : GameLib.D3.Scene,
'bufferCamera' : GameLib.D3.Camera,
'renderTarget' : GameLib.D3.RenderTarget,
'defaultScene' : GameLib.D3.Scene
}
);
};
GameLib.D3.Renderer.prototype = Object.create(GameLib.D3.API.Renderer.prototype);
GameLib.D3.Renderer.prototype.constructor = GameLib.D3.Renderer;
/**
* Create Renderer Instance
* @returns {*}
*/
GameLib.D3.Renderer.prototype.createInstance = function() {
if (GameLib.Utils.UndefinedOrNull(this.domElement)) {
throw new Error('no dom element');
}
if (GameLib.Utils.UndefinedOrNull(this.domElement.instance)) {
throw new Error('no dom element instance');
}
this.instance = new THREE.WebGLRenderer(
{
canvas : this.domElement.instance
}
);
if (this.clippingPlanes.length > 0) {
this.instance.clippingPlanes = this.clippingPlanes.map(
function(clippingPlane) {
if (!clippingPlane.isClippingPlane || !clippingPlane.instance || !clippingPlane.instance.clipping) {
throw new Error('is not a clipping plane or no clipping plane instance');
}
return clippingPlane.instance.clipping;
}
)
}
this.instance.localClippingEnabled = this.localClipping;
this.instance.setSize(
this.width,
this.height
);
this.instance.setClearColor(
new THREE.Color(
this.clearColor.r,
this.clearColor.g,
this.clearColor.b
),
1 - this.clearColor.a
);
this.instance.domElement.width = this.width;
this.instance.domElement.height = this.height;
this.instance.autoClear = this.autoClear;
this.instance.preserveDrawingBuffer = this.preserveDrawingBuffer;
this.instance.sortObjects = this.sortObjects;
GameLib.Component.prototype.createInstance.call(this);
};
/**
*
*/
GameLib.D3.Renderer.prototype.updateInstance = function(property) {
if (!this.instance) {
try {
this.createInstance();
} catch (error) {
console.error(error.message);
}
return;
}
if (!property) {
console.error('no property for renderer');
}
if (property === 'localClipping') {
this.instance.localClippingEnabled = this.localClipping;
}
if (property === 'width' || 'height') {
this.instance.setSize(
this.width,
this.height
);
this.instance.domElement.width = this.width;
this.instance.domElement.height = this.height;
}
if (property === 'clearColor') {
this.instance.setClearColor(
new THREE.Color(
this.clearColor.r,
this.clearColor.g,
this.clearColor.b
),
1 - this.clearColor.a
);
}
if (property === 'autoClear') {
this.instance.autoClear = this.autoClear;
}
if (property === 'preserveDrawingBuffer') {
this.instance.preserveDrawingBuffer = this.preserveDrawingBuffer;
}
if (this.clippingPlanes.length > 0) {
this.instance.clippingPlanes = this.clippingPlanes.map(
function(clippingPlane) {
if (!clippingPlane.isClippingPlane || !clippingPlane.instance || !clippingPlane.instance.clipping) {
throw new Error('is not a clipping plane or no clipping plane instance');
}
return clippingPlane.instance.clipping;
}
)
} else {
this.instance.clippingPlanes = [];
}
if (property === 'sortObjects') {
this.instance.sortObjects = this.sortObjects;
}
};
/**
*
* @returns {GameLib.D3.API.Renderer}
*/
GameLib.D3.Renderer.prototype.toApiObject = function() {
var apiRenderer = new GameLib.D3.API.Renderer(
this.id,
this.name,
this.autoClear,
this.localClipping,
this.width,
this.height,
this.preserveDrawingBuffer,
GameLib.Utils.IdOrNull(this.domElement),
this.clearColor.toApiObject(),
GameLib.Utils.IdOrNull(this.camera),
this.scenes.map(function(scene){
return GameLib.Utils.IdOrNull(scene);
}),
this.viewports.map(function(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.defaultScene),
this.sortObjects,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiRenderer;
};
/**
*
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.Renderer}
* @constructor
*/
GameLib.D3.Renderer.FromObject = function(graphics, objectComponent) {
var apiRenderer = GameLib.D3.API.Renderer.FromObject(objectComponent);
return new GameLib.D3.Renderer(
graphics,
apiRenderer
);
};
/**
* Convenience render function
*/
GameLib.D3.Renderer.prototype.render = function(delta, scenes) {
if (!this.instance) {
return;
}
if (GameLib.Utils.UndefinedOrNull(scenes)) {
scenes = this.scenes;
}
if (this.viewports.length > 1) {
this.instance.autoClear = false;
}
if (scenes.length > 1) {
this.instance.autoClear = false;
}
this.instance.clear();
if (
this.bufferScene &&
this.bufferScene.instance &&
this.bufferCamera &&
this.bufferCamera.instance &&
this.renderTarget &&
this.renderTarget.instance
) {
/**
* 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(
function(viewport) {
this.instance.setViewport(
viewport.x * this.width,
viewport.y * this.height,
viewport.width * this.width,
viewport.height * this.height
);
scenes.map(function(scene) {
if (!scene.instance) {
return;
}
if (!this.camera.instance && !(scene.renderCamera || scene.renderCamera.instance)) {
return;
}
/**
* A scene's renderCamera instance overrides the default renderer camera
*/
if (scene.renderCamera && scene.renderCamera.instance) {
this.instance.render(
scene.instance,
scene.renderCamera.instance
)
} else {
this.instance.render(
scene.instance,
this.camera.instance
)
}
}.bind(this));
}.bind(this)
);
};
GameLib.D3.Renderer.prototype.setSize = function(width, height) {
this.width = width;
this.height = height;
if (this.instance) {
this.instance.setSize(
this.width,
this.height
);
} else {
console.log('renderer not ready to set size');
}
};
/**
* RigidBody Runtime
* @param physics GameLib.D3.Graphics
* @param apiRigidBody GameLib.D3.API.RigidBody
* @constructor
*/
GameLib.D3.RigidBody = function (
physics,
apiRigidBody
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiRigidBody)) {
apiRigidBody = {};
}
if (apiRigidBody instanceof GameLib.D3.RigidBody) {
return apiRigidBody;
}
GameLib.D3.API.RigidBody.call(
this,
apiRigidBody.id,
apiRigidBody.name,
apiRigidBody.mass,
apiRigidBody.friction,
apiRigidBody.position,
apiRigidBody.quaternion,
apiRigidBody.velocity,
apiRigidBody.angularVelocity,
apiRigidBody.linearDamping,
apiRigidBody.angularDamping,
apiRigidBody.allowSleep,
apiRigidBody.sleepSpeedLimit,
apiRigidBody.sleepTimeLimit,
apiRigidBody.collisionFilterGroup,
apiRigidBody.collisionFilterMask,
apiRigidBody.fixedRotation,
apiRigidBody.shapes,
apiRigidBody.kinematic,
apiRigidBody.parentMesh,
apiRigidBody.parentWorld,
apiRigidBody.parentEntity
);
this.position = new GameLib.Vector3(
this.physics,
this.position,
this
);
this.quaternion = new GameLib.Quaternion(
this.physics,
this.quaternion,
this
);
this.velocity = new GameLib.Vector3(
this.physics,
this.velocity,
this
);
this.angularVelocity = new GameLib.Vector3(
this.physics,
this.angularVelocity,
this
);
this.force = new GameLib.Vector3(
this.physics
);
this.forcePoint = new GameLib.Vector3(
this.physics
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_RIGID_BODY,
{
'shapes' : [GameLib.D3.Shape],
'parentMesh' : GameLib.D3.Mesh,
'parentWorld' : GameLib.D3.PhysicsWorld
}
);
};
GameLib.D3.RigidBody.prototype = Object.create(GameLib.D3.API.RigidBody.prototype);
GameLib.D3.RigidBody.prototype.constructor = GameLib.D3.RigidBody;
/**
*
* @returns {*}
*/
GameLib.D3.RigidBody.prototype.createInstance = function() {
this.instance = new CANNON.Body(
{
mass : this.mass,
friction : this.friction,
position : this.position.instance,
quaternion : this.quaternion.instance,
velocity : this.velocity.instance,
angularVelocity : this.angularVelocity.instance,
linearDamping : this.linearDamping,
angularDamping : this.angularDamping,
allowSleep : this.allowSleep,
sleepSpeedLimit : this.sleepSpeedLimit,
sleepTimeLimit : this.sleepTimeLimit,
collisionFilterGroup : this.collisionFilterGroup,
collisionFilterMask : this.collisionFilterMask,
fixedRotation : this.fixedRotation,
kinematic : this.kinematic
}
);
this.instance.addEventListener(
"sleepy",
function() {
console.log(this.name + " is feeling sleepy...");
}.bind(this)
);
this.instance.addEventListener(
"sleep",
function() {
console.log(this.name + " fell asleep!");
}.bind(this)
);
this.instance.addEventListener(
"wakeup",
function() {
console.log(this.name + " woke up!");
}.bind(this)
);
this.shapes.map(
function(shape) {
if (GameLib.Utils.UndefinedOrNull(shape)) {
throw new Error('no shape');
}
if (GameLib.Utils.UndefinedOrNull(shape.instance)) {
throw new Error('no shape instance');
}
this.instance.addShape(shape.instance)
}.bind(this)
);
GameLib.Component.prototype.createInstance.call(this);
};
/**
*
*/
GameLib.D3.RigidBody.prototype.updateInstance = function() {
this.instance.mass = this.mass;
this.instance.friction = this.friction;
this.instance.position.x = this.position.x;
this.instance.position.y = this.position.y;
this.instance.position.z = this.position.z;
this.quaternion.axis.instance.x = this.quaternion.axis.x;
this.quaternion.axis.instance.y = this.quaternion.axis.y;
this.quaternion.axis.instance.z = this.quaternion.axis.z;
this.instance.quaternion.setFromAxisAngle(
this.quaternion.axis.instance,
this.quaternion.angle
);
this.quaternion.x = this.instance.quaternion.x;
this.quaternion.y = this.instance.quaternion.y;
this.quaternion.z = this.instance.quaternion.z;
this.quaternion.w = this.instance.quaternion.w;
this.parentMesh.position.setFrom(this.position);
this.parentMesh.quaternion.setFrom(this.quaternion);
this.parentMesh.updateInstance();
this.instance.velocity.x = this.velocity.x;
this.instance.velocity.y = this.velocity.y;
this.instance.velocity.z = this.velocity.z;
this.instance.angularVelocity.x = this.angularVelocity.x;
this.instance.angularVelocity.y = this.angularVelocity.y;
this.instance.angularVelocity.z = this.angularVelocity.z;
this.instance.linearDamping = this.linearDamping;
this.instance.angularDamping = this.angularDamping;
this.instance.allowSleep = this.allowSleep;
this.instance.sleepSpeedLimit = this.sleepSpeedLimit;
this.instance.sleepTimeLimit = this.sleepTimeLimit;
this.instance.collisionFilterGroup = this.collisionFilterGroup;
this.instance.collisionFilterMask = this.collisionFilterMask;
this.instance.fixedRotation = this.fixedRotation;
this.instance.kinematic = this.kinematic;
};
GameLib.D3.RigidBody.prototype.setFromParentMesh = function() {
if (!this.parentMesh || !this.parentMesh.instance) {
console.log('no parent mesh or instance');
}
this.instance.position.x = this.parentMesh.position.x;
this.instance.position.y = this.parentMesh.position.y;
this.instance.position.z = this.parentMesh.position.z;
this.instance.quaternion.x = this.parentMesh.quaternion.x;
this.instance.quaternion.y = this.parentMesh.quaternion.y;
this.instance.quaternion.z = this.parentMesh.quaternion.z;
this.instance.quaternion.w = this.parentMesh.quaternion.w;
// this.updateInstance();
};
/**
* GameLib.D3.RigidBody to GameLib.D3.API.RigidBody
* @returns {GameLib.D3.API.RigidBody}
*/
GameLib.D3.RigidBody.prototype.toApiObject = function() {
var apiRigidBody = new GameLib.D3.API.RigidBody(
this.id,
this.name,
this.mass,
this.friction,
this.position.toApiObject(),
this.quaternion.toApiObject(),
this.velocity.toApiObject(),
this.angularVelocity.toApiObject(),
this.linearDamping,
this.angularDamping,
this.allowSleep,
this.sleepSpeedLimit,
this.sleepTimeLimit,
this.collisionFilterGroup,
this.collisionFilterMask,
this.fixedRotation,
this.shapes.map(function(shape){return GameLib.Utils.IdOrNull(shape)}),
this.kinematic,
GameLib.Utils.IdOrNull(this.parentMesh),
GameLib.Utils.IdOrNull(this.parentWorld),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiRigidBody;
};
/**
* GameLib.D3.RigidBody from Object RigidBody
* @param physics
* @param objectComponent
* @returns {GameLib.D3.RigidBody}
* @constructor
*/
GameLib.D3.RigidBody.FromObject = function(physics, objectComponent) {
var apiRigidBody = GameLib.D3.API.RigidBody.FromObject(objectComponent);
return new GameLib.D3.RigidBody(
physics,
apiRigidBody
);
};
GameLib.D3.RigidBody.prototype.applyForce = function() {
this.instance.applyForce(
this.force.instance,
this.forcePoint.instance
)
};
GameLib.D3.RigidBody.prototype.applyLocalForce = function() {
this.instance.applyLocalForce(
this.force.instance,
this.forcePoint.instance
)
};
/**
* Scene Superset - The apiScene properties get moved into the Scene object itself, and then the instance is
* created
* @param graphics
* @param apiScene GameLib.D3.API.Scene
* @constructor
*/
GameLib.D3.Scene = function (
graphics,
apiScene
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiScene)) {
apiScene = {};
}
if (apiScene instanceof GameLib.D3.Scene) {
return apiScene;
}
GameLib.D3.API.Scene.call(
this,
apiScene.id,
apiScene.name,
apiScene.meshes,
apiScene.lights,
apiScene.textures,
apiScene.materials,
apiScene.images,
apiScene.fog,
apiScene.renderCamera,
apiScene.showGrid,
apiScene.showAxis,
apiScene.gridSize,
apiScene.gridColor,
apiScene.parentEntity
);
this.meshes = this.meshes.map(
function(apiMesh) {
if (apiMesh instanceof GameLib.D3.API.Mesh) {
apiMesh.parentScene = this;
return new GameLib.D3.Mesh(
this.graphics,
apiMesh
);
} else {
return apiMesh;
}
}.bind(this)
);
this.lights = this.lights.map(
function(apiLight) {
if (apiLight instanceof GameLib.D3.API.Light) {
return new GameLib.D3.Light(
this.graphics,
apiLight
);
} else {
return apiLight;
}
}.bind(this)
);
this.textures = this.textures.map(
function(apiTexture) {
if (apiTexture instanceof GameLib.D3.API.Texture) {
var texture = new GameLib.D3.Texture(
this.graphics,
apiTexture
);
return texture;
} else {
return apiTexture;
}
}.bind(this)
);
this.materials = this.materials.map(
function(apiMaterial) {
if (apiMaterial instanceof GameLib.D3.API.Material) {
var material = new GameLib.D3.Material(
this.graphics,
apiMaterial
);
return material;
} else {
return apiMaterial;
}
}.bind(this)
);
this.images = this.images.map(
function(apiImage) {
if (apiImage instanceof GameLib.D3.API.Image) {
var image = new GameLib.D3.Image(
this.graphics,
apiImage
);
return image;
} else {
return apiImage;
}
}.bind(this)
);
if (this.fog instanceof GameLib.D3.API.Fog) {
this.fog = new GameLib.D3.Fog(
this.graphics,
this.fog
)
}
if (this.renderCamera instanceof GameLib.D3.API.Camera) {
this.renderCamera = new GameLib.D3.Camera(
this.graphics,
this.renderCamera
)
}
if (this.gridColor instanceof GameLib.API.Color) {
this.gridColor = new GameLib.Color(
this.graphics,
this.gridColor,
this
)
}
/**
* Runtime scenes have helpers (just used to store which helper belongs to which scene)
* @type {Array}
*/
this.helpers = [];
this.clones = [];
this.grid = [];
this.axis = [];
this.storeClones = false;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_SCENE,
{
'meshes' : [GameLib.D3.Mesh],
'lights' : [GameLib.D3.Light],
'textures' : [GameLib.D3.Texture],
'materials' : [GameLib.D3.Material],
'images' : [GameLib.D3.Image],
'fog' : GameLib.D3.Fog,
'renderCamera' : GameLib.D3.Camera
}
);
};
GameLib.D3.Scene.prototype = Object.create(GameLib.D3.API.Scene.prototype);
GameLib.D3.Scene.prototype.constructor = GameLib.D3.Scene;
/**
* Creates an instance scene
* @returns {THREE.Scene}
*/
GameLib.D3.Scene.prototype.createInstance = function() {
this.instance = new THREE.Scene();
this.instance.name = this.name;
if (this.fog && this.fog.instance) {
this.instance.fog = this.fog.instance;
}
this.meshes.map(
function(mesh) {
if (GameLib.Utils.UndefinedOrNull(mesh)) {
throw new Error('no mesh');
}
if (GameLib.Utils.UndefinedOrNull(mesh.instance)) {
throw new Error('no mesh instance');
}
this.instance.add(mesh.instance);
mesh.parentScene = this;
}.bind(this)
);
this.lights.map(
function(light) {
if (GameLib.Utils.UndefinedOrNull(light)) {
throw new Error('no light');
}
if (GameLib.Utils.UndefinedOrNull(light.instance)) {
throw new Error('no light instance');
}
this.instance.add(light.instance);
light.parentScene = this;
}.bind(this)
);
if (this.showGrid) {
this.drawGrid();
}
if (this.showAxis) {
this.drawAxis();
}
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.D3.Scene.prototype.updateInstance = function(property) {
if (property === 'name') {
this.instance.name = this.name;
return;
}
if (this.fog && this.fog.instance !== this.instance.fog) {
this.instance.fog = this.fog.instance;
}
/**
* Add missing meshes
*/
this.meshes.map(
function(mesh) {
if (this.instance.children.indexOf(mesh.instance === -1)) {
this.instance.add(mesh.instance);
}
}.bind(this)
);
/**
* Add missing lights
*/
this.lights.map(
function(light) {
if (this.instance.children.indexOf(light.instance) === -1) {
this.instance.add(light.instance);
}
}.bind(this)
);
/**
* Remove extra meshes and lights
*/
this.instance.children.map(
function(instanceObject) {
var instanceMeshes = this.meshes.map(
function(mesh) {
return mesh.instance;
}
);
var instanceLights = this.lights.map(
function(light) {
return light.instance;
}
);
if (
(
instanceObject instanceof THREE.Mesh ||
instanceObject instanceof THREE.Light
) &&
(
instanceLights.indexOf(instanceObject) === -1 &&
instanceMeshes.indexOf(instanceObject) === -1
)
) {
this.instance.remove(instanceObject);
}
}.bind(this)
);
if (
property === 'showGrid' ||
property === 'gridSize' ||
property === 'gridColor'
) {
if (this.showGrid) {
this.drawGrid();
} else {
this.removeGrid();
}
}
if (property === 'showAxis') {
if (this.showAxis) {
this.drawAxis();
} else {
this.removeAxis();
}
}
};
/**
* Converts a GameLib.D3.Scene to a GameLib.D3.API.Scene
* @returns {GameLib.D3.API.Scene}
*/
GameLib.D3.Scene.prototype.toApiObject = function() {
var apiMeshes = this.meshes.reduce(
function(result, mesh) {
/**
* Do not store any cloned meshes
*/
if ((this.clones.indexOf(mesh) === -1) || this.storeClones) {
result.push(GameLib.Utils.IdOrNull(mesh));
}
return result;
}.bind(this),
[]
);
var apiLights = this.lights.reduce(
function(result, light) {
/**
* Do not store any cloned lights
*/
if (this.clones.indexOf(light) === -1 || this.storeClones) {
result.push(GameLib.Utils.IdOrNull(light));
}
return result;
}.bind(this),
[]
);
var apiTextures = this.textures.map(
function(texture) {
return GameLib.Utils.IdOrNull(texture);
}
);
var apiMaterials = this.materials.map(
function(material) {
return GameLib.Utils.IdOrNull(material);
}
);
var apiImages = this.images.map(
function(image) {
return GameLib.Utils.IdOrNull(image);
}
);
return new GameLib.D3.API.Scene(
this.id,
this.name,
apiMeshes,
apiLights,
apiTextures,
apiMaterials,
apiImages,
GameLib.Utils.IdOrNull(this.fog),
GameLib.Utils.IdOrNull(this.renderCamera),
this.showGrid,
this.showAxis,
this.gridSize,
this.gridColor.toApiObject(),
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Converts a scene Object to a GameLib.D3.Scene object
* @param graphics GameLib.D3.Graphics
* @param objectScene Object
* @returns {GameLib.D3.Scene}
* @constructor
*/
GameLib.D3.Scene.FromObject = function(
graphics,
objectScene
) {
var apiScene = GameLib.D3.API.Scene.FromObject(objectScene);
return new GameLib.D3.Scene(
graphics,
apiScene
);
};
/**
* Adds a mesh to the scene
* @param object GameLib.D3.Mesh
*/
GameLib.D3.Scene.prototype.addObject = function(object) {
if (object instanceof GameLib.D3.Mesh) {
if (this.meshes.indexOf(object) === -1) {
this.meshes.push(object);
}
} else if (object instanceof GameLib.D3.API.Mesh) {
object = new GameLib.D3.Mesh(
this.graphics,
object
);
this.meshes.push(object);
}
if (object instanceof GameLib.D3.Light) {
if (this.lights.indexOf(object) === -1) {
this.lights.push(object);
}
} else if (object instanceof GameLib.D3.API.Light) {
object = new GameLib.D3.Light(
this.graphics,
object
);
this.lights.push(object);
}
object.parentScene = this;
if (
this.instance &&
object.instance
) {
if (this.instance.children.indexOf(object.instance) === -1) {
this.instance.add(object.instance);
}
}
};
GameLib.D3.Scene.prototype.addClone = function(component) {
if (component instanceof GameLib.D3.Mesh ||
component instanceof GameLib.D3.Light
) {
if (this.instance && component.instance) {
this.instance.add(component.instance);
}
GameLib.Utils.PushUnique(this.clones, component);
component.parentScene = this;
}
};
/**
*
* @param object
*/
GameLib.D3.Scene.prototype.removeObject = function(object) {
var index = -1;
if (object instanceof GameLib.D3.Mesh) {
index = this.meshes.indexOf(object);
if (index !== -1) {
this.meshes.splice(index, 1);
}
index = this.clones.indexOf(object);
if (index !== -1) {
this.clones.splice(index, 1);
}
} else if (object instanceof GameLib.D3.Light) {
index = this.lights.indexOf(object);
if (index !== -1) {
this.lights.splice(index, 1);
}
index = this.clones.indexOf(object);
if (index !== -1) {
this.clones.splice(index, 1);
}
} else {
console.warn('Cannot remove this object - what is this ?' + object.toString());
return;
}
if (this.instance.children.indexOf(object.instance) !== -1) {
this.instance.remove(object.instance);
} else {
console.warn('no scene instance');
}
if (object.parentScene === this) {
object.parentScene = null;
}
// this.buildIdToObject();
};
GameLib.D3.Scene.prototype.drawGrid = function() {
this.removeGrid();
var lineMaterial = new THREE.LineBasicMaterial({
color: this.gridColor.toHex(),
linewidth: 1
});
for (var y = -this.gridSize; y <= this.gridSize; y += 1) {
var Xgeometry = new THREE.Geometry();
Xgeometry.vertices.push(
new THREE.Vector3( y, 0, this.gridSize * -1 ),
new THREE.Vector3( y, 0, this.gridSize )
);
var lineX = new THREE.Line(Xgeometry, lineMaterial);
this.instance.add(lineX);
this.grid.push(lineX);
var Ygeometry = new THREE.Geometry();
Ygeometry.vertices.push(
new THREE.Vector3( this.gridSize * -1 , 0, y ),
new THREE.Vector3( this.gridSize, 0, y )
);
var lineY = new THREE.Line(Ygeometry, lineMaterial);
this.instance.add(lineY);
this.grid.push(lineY);
}
};
GameLib.D3.Scene.prototype.removeGrid = function() {
this.grid.map(
function(object) {
this.instance.remove(object);
}.bind(this)
);
};
GameLib.D3.Scene.prototype.drawAxis = function() {
this.removeAxis();
var Xmaterial = new THREE.LineBasicMaterial({
color: 0xff0000,
linewidth: 2
});
var Xgeometry = new THREE.Geometry();
Xgeometry.vertices.push(
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 100, 0, 0 )
);
var lineX = new THREE.Line(Xgeometry, Xmaterial);
this.instance.add(lineX);
this.axis.push(lineX);
var Ymaterial = new THREE.LineBasicMaterial({
color: 0x00ff00,
linewidth: 2
});
var Ygeometry = new THREE.Geometry();
Ygeometry.vertices.push(
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 0, 100, 0 )
);
var lineY = new THREE.Line(Ygeometry, Ymaterial);
this.instance.add(lineY);
this.axis.push(lineY);
var Zmaterial = new THREE.LineBasicMaterial({
color: 0x0000ff,
linewidth: 2
});
var Zgeometry = new THREE.Geometry();
Zgeometry.vertices.push(
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 0, 0, 100 )
);
var lineZ = new THREE.Line(Zgeometry, Zmaterial);
this.instance.add(lineZ);
this.axis.push(lineZ);
};
GameLib.D3.Scene.prototype.removeAxis = function() {
this.axis.map(
function(object) {
this.instance.remove(object);
}.bind(this)
);
};
/**
* Shape Superset - The apiShape properties get moved into the Shape object itself, and then the instance is created
* @param physics GameLib.D3.Physics
* @param apiShape GameLib.D3.API.Shape
* @constructor
*/
GameLib.D3.Shape = function (
physics,
apiShape
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiShape)) {
apiShape = {};
}
if (apiShape instanceof GameLib.D3.Shape) {
return apiShape;
}
GameLib.D3.API.Shape.call(
this,
apiShape.id,
apiShape.name,
apiShape.boundingSphereRadius,
apiShape.collisionResponse,
apiShape.frictionMaterial,
apiShape.parentMesh,
apiShape.parentEntity
);
var componentType = GameLib.Component.COMPONENT_SHAPE;
var linkedObjects = {
frictionMaterial : GameLib.D3.FrictionMaterial,
parentMesh : GameLib.D3.Mesh
};
if (this instanceof GameLib.D3.Shape.Box) {
componentType = GameLib.Component.COMPONENT_SHAPE_BOX;
}
if (this instanceof GameLib.D3.Shape.ConvexHull) {
componentType = GameLib.Component.COMPONENT_SHAPE_CONVEX_HULL;
}
if (this instanceof GameLib.D3.Shape.ConvexHull.Cylinder) {
componentType = GameLib.Component.COMPONENT_SHAPE_CONVEX_HULL_CYLINDER;
}
if (this instanceof GameLib.D3.Shape.Sphere) {
componentType = GameLib.Component.COMPONENT_SHAPE_SPHERE;
}
if (this instanceof GameLib.D3.Shape.TriMesh) {
componentType = GameLib.Component.COMPONENT_SHAPE_TRI_MESH;
}
if (this instanceof GameLib.D3.Shape.Plane) {
componentType = GameLib.Component.COMPONENT_SHAPE_PLANE;
}
if (this instanceof GameLib.D3.Shape.HeightMap) {
componentType = GameLib.Component.COMPONENT_SHAPE_HEIGHT_MAP;
}
GameLib.Component.call(
this,
componentType,
linkedObjects
);
};
GameLib.D3.Shape.prototype = Object.create(GameLib.D3.API.Shape.prototype);
GameLib.D3.Shape.prototype.constructor = GameLib.D3.Shape;
/**
* Creates a shape instance or updates it
*/
GameLib.D3.Shape.prototype.createInstance = function() {
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the mesh instance
*/
GameLib.D3.Shape.prototype.updateInstance = function() {
throw new Error('Do not instantiate this class directly - use a child class instead');
};
/**
* Converts a GameLib.D3.Shape to a GameLib.D3.API.Shape
* @returns {GameLib.D3.API.Shape}
*/
GameLib.D3.Shape.prototype.toApiObject = function() {
var apiShape = new GameLib.D3.API.Shape(
this.id,
this.name,
this.boundingSphereRadius,
this.collisionResponse,
GameLib.Utils.IdOrNull(this.frictionMaterial),
GameLib.Utils.IdOrNull(this.parentMesh),
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiShape;
};
/**
* Converts a standard object mesh to a GameLib.D3.Shape
* @param physics GameLib.D3.Physics
* @param objectShape {Object}
* @constructor
*/
GameLib.D3.Shape.FromObject = function(physics, objectShape) {
throw ('not implemented');
};
GameLib.D3.Shape.prototype.stopVisualize = function() {
GameLib.Event.Emit(
GameLib.Event.STOP_VISUALIZE,
{
mesh : this.mesh
}
)
};
GameLib.D3.Shape.prototype.visualize = function() {
GameLib.Event.Emit(
GameLib.Event.VISUALIZE,
{
shape : this
}
)
};
/**
* Shape Superset - The apiShape properties get moved into the Shape object itself, and then the instance is created
* @param physics
* @param apiShape GameLib.D3.API.Shape
* @param halfExtents
* @constructor
*/
GameLib.D3.Shape.Box = function (
physics,
apiShape,
halfExtents
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(halfExtents)) {
halfExtents = new GameLib.Vector3(
physics,
new GameLib.API.Vector3(
1,1,1
)
);
} else if (halfExtents instanceof GameLib.API.Vector3) {
halfExtents = new GameLib.Vector3(
this.physics,
halfExtents,
this
)
}
this.halfExtents = halfExtents;
GameLib.D3.Shape.call(
this,
this.physics,
apiShape
);
};
GameLib.D3.Shape.Box.prototype = Object.create(GameLib.D3.Shape.prototype);
GameLib.D3.Shape.Box.prototype.constructor = GameLib.D3.Shape.Box;
/**
*
* @returns {GameLib.D3.Shape.Box|*|SEA3D.Box}
*/
GameLib.D3.Shape.Box.prototype.createInstance = function() {
if (GameLib.Utils.UndefinedOrNull(this.halfExtents)) {
throw new Error('no halfExtents');
}
if (GameLib.Utils.UndefinedOrNull(this.halfExtents.instance)) {
throw new Error('no halfExtents instance');
}
this.instance = new CANNON.Box(
this.halfExtents.instance
);
GameLib.D3.Shape.prototype.createInstance.call(this);
};
GameLib.D3.Shape.Box.prototype.updateInstance = function() {
this.instance.halfExtents.x = this.halfExtents.x;
this.instance.halfExtents.y = this.halfExtents.y;
this.instance.halfExtents.z = this.halfExtents.z;
this.instance.updateBoundingSphereRadius();
this.instance.updateConvexPolyhedronRepresentation();
};
GameLib.D3.Shape.Box.prototype.toApiObject = function() {
var apiShape = GameLib.D3.Shape.prototype.toApiObject.call(this);
apiShape.halfExtents = this.halfExtents.toApiObject();
return apiShape;
};
GameLib.D3.Shape.Box.prototype.setFromMesh = function() {
if (this.parentMesh === null) {
console.log('select a mesh first');
return;
}
var box = this.parentMesh.getBoundingBox();
this.halfExtents.x = box.x / 2;
this.halfExtents.y = box.y / 2;
this.halfExtents.z = box.z / 2;
this.halfExtents.updateInstance();
};
GameLib.D3.Shape.Box.FromObject = function(physics, objectShape) {
var apiShape = GameLib.D3.API.Shape.FromObject(objectShape);
apiShape.halfExtents = GameLib.API.Vector3.FromObject(objectShape.halfExtents);
return new GameLib.D3.Shape.Box(
physics,
apiShape,
apiShape.halfExtents
);
};
/**
* Shape Superset - The apiShape properties get moved into the Shape object itself, and then the instance is created
* @param physics
* @param apiShape GameLib.D3.API.Shape
* @param faces
* @param uniqueAxes
* @param uniqueEdges
* @param vertices
* @constructor
*/
GameLib.D3.Shape.ConvexHull = function (
physics,
apiShape,
vertices,
faces,
uniqueAxes,
uniqueEdges
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiShape)) {
apiShape = {};
}
if (apiShape instanceof GameLib.D3.Shape.ConvexHull) {
return apiShape;
}
if (GameLib.Utils.UndefinedOrNull(vertices)) {
vertices = [];
}
this.vertices = vertices;
if (GameLib.Utils.UndefinedOrNull(faces)) {
faces = [];
}
this.faces = faces;
if (GameLib.Utils.UndefinedOrNull(uniqueAxes)) {
uniqueAxes = [];
}
this.uniqueAxes = uniqueAxes;
if (GameLib.Utils.UndefinedOrNull(uniqueEdges)) {
uniqueEdges = [];
}
this.uniqueEdges = uniqueEdges;
this.vertices = this.vertices.map(function(vertex){
if (vertex instanceof GameLib.D3.API.Vertex){
return new GameLib.D3.Vertex(
this.physics,
vertex
)
}
return vertex;
}.bind(this));
this.faces = this.faces.map(function(face){
if (face instanceof GameLib.D3.API.Face){
return new GameLib.D3.Face(
this.physics,
face
)
}
return face;
}.bind(this));
this.uniqueAxes = this.uniqueAxes.map(function(axis){
if (axis instanceof GameLib.API.Vector3) {
return new GameLib.Vector3(
this.physics,
axis,
this
)
}
return axis;
}.bind(this));
this.uniqueEdges = this.uniqueEdges.map(function(edge){
if (edge instanceof GameLib.API.Vector3) {
return new GameLib.Vector3(
this.physics,
edge,
this
)
}
return edge;
}.bind(this));
GameLib.D3.Shape.call(
this,
this.physics,
apiShape
);
};
GameLib.D3.Shape.ConvexHull.prototype = Object.create(GameLib.D3.Shape.prototype);
GameLib.D3.Shape.ConvexHull.prototype.constructor = GameLib.D3.Shape.ConvexHull;
/**
* Create instance
* @returns {GameLib.D3.Shape.ConvexHull}
*/
GameLib.D3.Shape.ConvexHull.prototype.createInstance = function() {
var faceNormals = [];
this.instance = new CANNON.ConvexPolyhedron(
this.vertices.map(
function(vertex) {
if (GameLib.Utils.UndefinedOrNull(vertex)) {
throw new Error('no vertex');
}
if (GameLib.Utils.UndefinedOrNull(vertex.position)) {
throw new Error('no vertex position');
}
if (GameLib.Utils.UndefinedOrNull(vertex.position.instance)) {
throw new Error('no vertex position instance');
}
return vertex.position.instance;
}
),
this.faces.map(
function(face) {
if (GameLib.Utils.UndefinedOrNull(face)) {
throw new Error('no face');
}
if (GameLib.Utils.UndefinedOrNull(face.normal)) {
throw new Error('no face normal');
}
if (GameLib.Utils.UndefinedOrNull(face.normal.instance)) {
throw new Error('no face normal instance');
}
if (GameLib.Utils.UndefinedOrNull(face.v0index)) {
throw new Error('no face v0index');
}
if (GameLib.Utils.UndefinedOrNull(face.v1index)) {
throw new Error('no face v1index');
}
if (GameLib.Utils.UndefinedOrNull(face.v2index)) {
throw new Error('no face v2index');
}
faceNormals.push(face.normal.instance);
return [face.v0index, face.v1index, face.v2index];
}
)
);
this.instance.faceNormals = faceNormals;
GameLib.D3.Shape.prototype.createInstance.call(this);
};
/**
* Update instance
*/
GameLib.D3.Shape.ConvexHull.prototype.updateInstance = function() {
console.log('todo: update convex hull instance');
// this.instance.vertices = this.vertices;
// this.instance.indices = this.indices;
// this.instance.updateAABB();
// this.instance.updateBoundingSphereRadius();
// this.instance.updateEdges();
// this.instance.updateNormals();
// this.instance.updateTree();
};
GameLib.D3.Shape.ConvexHull.prototype.loadFromInstance = function() {
console.log('todo: eventually load the faces and vertices from the instance faces and vertices and normals');
console.log('todo: this way we can nicely visualize them with our gamelib classes :)');
};
GameLib.D3.Shape.ConvexHull.prototype.toApiObject = function() {
var apiShape = GameLib.D3.Shape.prototype.toApiObject.call(this);
apiShape.vertices = this.vertices.map(
function(vertex) {
if (vertex instanceof GameLib.D3.Vertex) {
return vertex.toApiObject();
}
return vertex;
}
);
apiShape.faces = this.faces.map(
function(face) {
if (face instanceof GameLib.D3.Face){
return face.toApiObject();
}
return face;
}
);
apiShape.uniqueAxes = this.uniqueAxes.map(
function(axis){
if (axis instanceof GameLib.Vector3) {
return axis.toApiObject();
}
return axis;
}
);
apiShape.uniqueEdges = this.uniqueEdges.map(
function(edge) {
if (edge instanceof GameLib.Vector3) {
return edge.toApiObject();
}
return edge;
}
);
return apiShape;
};
GameLib.D3.Shape.ConvexHull.prototype.setFromMesh = function() {
console.log('todo: set convex hull from mesh');
this.updateInstance();
};
GameLib.D3.Shape.ConvexHull.InheritableProperties = function(physics, objectShape) {
var vertices = objectShape.vertices.map(
function(objectVertex) {
return GameLib.D3.Vertex.FromObject(physics, objectVertex);
}
);
var faces = objectShape.faces.map(
function(objectFace) {
return GameLib.D3.Face.FromObject(physics, objectFace);
}
);
var uniqueAxes = objectShape.uniqueAxes.map(
function(axis) {
return GameLib.API.Vector3.FromObject(axis);
}
);
var uniqueEdges = objectShape.uniqueEdges.map(
function(edge) {
return GameLib.API.Vector3.FromObject(edge);
}
);
return {
vertices : vertices,
faces : faces,
uniqueAxes : uniqueAxes,
uniqueEdges : uniqueEdges
};
};
GameLib.D3.Shape.ConvexHull.FromObject = function(physics, objectShape) {
var apiShape = GameLib.D3.API.Shape.FromObject(objectShape);
var inheritableProperties = GameLib.D3.Shape.ConvexHull.InheritableProperties(physics, objectShape);
return new GameLib.D3.Shape.ConvexHull.call(
this,
physics,
apiShape,
inheritableProperties.vertices,
inheritableProperties.faces,
inheritableProperties.uniqueAxes,
inheritableProperties.uniqueEdges
);
};
/**
* Shape Superset - The apiShape properties get moved into the Shape object itself, and then the instance is created
* @param physics
* @param apiShape GameLib.D3.API.Shape
* @param radiusTop
* @param radiusBottom
* @param height
* @param numSegments
* @constructor
*/
GameLib.D3.Shape.ConvexHull.Cylinder = function (
physics,
apiShape,
radiusTop,
radiusBottom,
height,
numSegments
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(radiusTop)) {
radiusTop = 1;
}
this.radiusTop = radiusTop;
if (GameLib.Utils.UndefinedOrNull(radiusBottom)) {
radiusBottom = 1;
}
this.radiusBottom = radiusBottom;
if (GameLib.Utils.UndefinedOrNull(height)) {
height = radiusBottom / 2;
}
this.height = height;
if (GameLib.Utils.UndefinedOrNull(numSegments)) {
numSegments = 20;
}
this.numSegments = numSegments;
GameLib.D3.Shape.ConvexHull.call(
this,
this.physics,
apiShape
);
};
GameLib.D3.Shape.ConvexHull.Cylinder.prototype = Object.create(GameLib.D3.Shape.ConvexHull.prototype);
GameLib.D3.Shape.ConvexHull.Cylinder.prototype.constructor = GameLib.D3.Shape.ConvexHull.Cylinder;
/**
*
* @returns {GameLib.D3.Shape.Cylinder|*|SEA3D.Cylinder}
*/
GameLib.D3.Shape.ConvexHull.Cylinder.prototype.createInstance = function() {
this.instance = new CANNON.Cylinder(
this.radiusTop,
this.radiusBottom,
this.height,
this.numSegments
);
GameLib.D3.Shape.prototype.createInstance.call(this);
};
GameLib.D3.Shape.ConvexHull.Cylinder.prototype.updateInstance = function() {
console.log('todo : update cylinder instance');
// this.instance.radius = this.radius;
// this.instance.updateAABB();
// this.instance.updateBoundingCylinderRadius();
// this.instance.updateEdges();
// this.instance.updateNormals();
// this.instance.updateTree();
};
GameLib.D3.Shape.ConvexHull.Cylinder.prototype.setFromMesh = function() {
this.radiusTop = this.parentMesh.dimensions.x / 2;
this.radiusBottom = this.parentMesh.dimensions.x / 2;
this.height = this.parentMesh.dimensions.z;
};
GameLib.D3.Shape.ConvexHull.Cylinder.prototype.toApiObject = function() {
var apiShape = GameLib.D3.Shape.ConvexHull.prototype.toApiObject.call(this);
apiShape.radiusTop = this.radiusTop;
apiShape.radiusBottom = this.radiusBottom;
apiShape.height = this.height;
apiShape.numSegments = this.numSegments;
return apiShape;
};
GameLib.D3.Shape.ConvexHull.Cylinder.FromObject = function(physics, objectShape) {
/**
* Just a reminder that below line is wrong and commented out - we need to call the constructors eventually with
* the right 'this' parameter and args.
*
* var apiShape = GameLib.D3.Shape.ConvexHull.FromObject(physics, objectShape);
*
* Instead, do this:
*/
var apiShape = GameLib.D3.API.Shape.FromObject(objectShape);
var inheritableProperties = GameLib.D3.Shape.ConvexHull.InheritableProperties(physics, objectShape);
for (var property in inheritableProperties) {
if (inheritableProperties.hasOwnProperty(property)) {
apiShape[property] = inheritableProperties[property];
}
}
return new GameLib.D3.Shape.ConvexHull.Cylinder(
physics,
apiShape,
objectShape.radiusTop,
objectShape.radiusBottom,
objectShape.height,
objectShape.numSegments
);
};
/**
*
* @param physics
* @param apiShape
* @param heightData
* @param minValue
* @param maxValue
* @param elementSize
* @constructor
*/
GameLib.D3.Shape.HeightMap = function (
physics,
apiShape,
heightData,
minValue,
maxValue,
elementSize
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(heightData)) {
heightData = [[10, 10, 10], [10, 10, 10], [10, 10, 10]];
}
this.heightData = heightData;
if (GameLib.Utils.UndefinedOrNull(minValue)) {
minValue = 0;
}
this.minValue = minValue;
if (GameLib.Utils.UndefinedOrNull(maxValue)) {
maxValue = 10;
}
this.maxValue = maxValue;
if (GameLib.Utils.UndefinedOrNull(elementSize)) {
elementSize = 1;
}
this.elementSize = elementSize;
GameLib.D3.Shape.call(
this,
this.physics,
apiShape
);
};
GameLib.D3.Shape.HeightMap.prototype = Object.create(GameLib.D3.Shape.prototype);
GameLib.D3.Shape.HeightMap.prototype.constructor = GameLib.D3.Shape.HeightMap;
/**
* Create instance
* @returns {GameLib.D3.Shape.HeightMap}
*/
GameLib.D3.Shape.HeightMap.prototype.createInstance = function() {
//TODO: initialize properly and throw when errors
this.instance = new CANNON.Heightfield(
this.heightData,
{
elemSize : this.elementSize
}
);
GameLib.D3.Shape.prototype.createInstance.call(this);
};
/**
* Update instance
*/
GameLib.D3.Shape.HeightMap.prototype.updateInstance = function() {
this.instance.data = this.heightData;
// this.instance.minValue = this.minValue;
// this.instance.maxValue = this.maxValue;
this.instance.elemSize = this.elemSize;
this.instance.update();
// this.instance.updateBoundingSphereRadius();
// this.instance.updateMaxValue();
// this.instance.updateMinValue();
};
GameLib.D3.Shape.HeightMap.prototype.toApiObject = function() {
var apiShape = GameLib.D3.Shape.prototype.toApiObject.call(this);
apiShape.heightData = this.heightData;
apiShape.minValue = this.minValue;
apiShape.maxValue = this.maxValue;
apiShape.elemSize = this.elemSize;
return apiShape;
};
GameLib.D3.Shape.HeightMap.prototype.setFromMesh = function() {
if (this.parentMesh === null) {
console.log('select a mesh first');
return;
}
if (!this.parentMesh.isHeightMap) {
console.log('not a heightmap mesh');
return;
}
var dim1Array = Array.prototype.slice.call(this.parentMesh.getHeightData());
// var w = this.parentMesh.widthSegments + 1;
//
// var h = 0;
// var offset = 0;
this.heightData = [];
for (var x = 0; x <= this.parentMesh.widthSegments; x++) {
this.heightData[x] = [];
for (var y = 0; y <= this.parentMesh.heightSegments; y++) {
this.heightData[x][y] = dim1Array[((x * (this.parentMesh.widthSegments + 1)) + y)];
}
}
// this.heightData = dim1Array.reduce(
// function(result, value) {
//
// result[h].push(value);
//
// w--;
//
// if (w === 0) {
// w = this.parentMesh.widthSegments;
//
// if (h < this.parentMesh.heightSegments) {
// h++;
// }
// }
//
// return result;
// }.bind(this),
// result
// );
this.updateInstance();
};
GameLib.D3.Shape.HeightMap.FromObject = function(physics, objectShape) {
var apiShape = GameLib.D3.API.Shape.FromObject(objectShape);
return new GameLib.D3.Shape.HeightMap(
physics,
apiShape,
objectShape.heightData,
objectShape.minValue,
objectShape.maxValue,
objectShape.elemSize
);
};
/**
* Shape Superset - The apiShape properties get moved into the Shape object itself, and then the instance is created
* @param physics
* @param apiShape GameLib.D3.API.Shape
* @constructor
*/
GameLib.D3.Shape.Plane = function (
physics,
apiShape
) {
this.physics = physics;
this.physics.isNotCannonThrow();
GameLib.D3.Shape.call(
this,
this.physics,
apiShape
);
};
GameLib.D3.Shape.Plane.prototype = Object.create(GameLib.D3.Shape.prototype);
GameLib.D3.Shape.Plane.prototype.constructor = GameLib.D3.Shape.Plane;
/**
*
* @returns {GameLib.D3.Shape.Plane|*|SEA3D.Plane}
*/
GameLib.D3.Shape.Plane.prototype.createInstance = function() {
/**
* A plane is just a plane at z = 0, to rotate it put it inside a rigid body and rotate the body
*/
this.instance = new CANNON.Plane();
GameLib.D3.Shape.prototype.createInstance.call(this);
};
GameLib.D3.Shape.Plane.prototype.updateInstance = function() {
};
GameLib.D3.Shape.Plane.FromObject = function(physics, objectShape) {
var apiShape = GameLib.D3.API.Shape.FromObject(objectShape);
return new GameLib.D3.Shape.Plane(
physics,
apiShape
);
};
/**
* Shape Superset - The apiShape properties get moved into the Shape object itself, and then the instance is created
* @param physics
* @param apiShape GameLib.D3.API.Shape
* @param radius
* @constructor
*/
GameLib.D3.Shape.Sphere = function (
physics,
apiShape,
radius
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(radius)) {
radius = 1;
}
this.radius = radius;
GameLib.D3.Shape.call(
this,
this.physics,
apiShape
);
};
GameLib.D3.Shape.Sphere.prototype = Object.create(GameLib.D3.Shape.prototype);
GameLib.D3.Shape.Sphere.prototype.constructor = GameLib.D3.Shape.Sphere;
/**
*
* @returns {GameLib.D3.Shape.Sphere|*|SEA3D.Sphere}
*/
GameLib.D3.Shape.Sphere.prototype.createInstance = function() {
this.instance = new CANNON.Sphere(
this.radius
);
GameLib.D3.Shape.prototype.createInstance.call(this);
};
GameLib.D3.Shape.Sphere.prototype.updateInstance = function() {
this.instance.radius = this.radius;
this.instance.updateBoundingSphereRadius();
};
GameLib.D3.Shape.Sphere.prototype.toApiObject = function() {
var apiShape = GameLib.D3.Shape.prototype.toApiObject.call(this);
apiShape.radius = this.radius;
return apiShape;
};
GameLib.D3.Shape.Sphere.FromObject = function(physics, objectShape) {
var apiShape = GameLib.D3.API.Shape.FromObject(objectShape);
return new GameLib.D3.Shape.Sphere(
physics,
apiShape,
objectShape.radius
);
};
/**
* Shape Superset - The apiShape properties get moved into the Shape object itself, and then the instance is created
* @param physics
* @param apiShape GameLib.D3.API.Shape
* @param vertices
* @param indices
* @constructor
*/
GameLib.D3.Shape.TriMesh = function (
physics,
apiShape,
vertices,
indices
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(vertices)) {
vertices = [];
}
this.vertices = vertices;
if (GameLib.Utils.UndefinedOrNull(indices)) {
indices = [];
}
this.indices = indices;
GameLib.D3.Shape.call(
this,
this.physics,
apiShape
);
};
GameLib.D3.Shape.TriMesh.prototype = Object.create(GameLib.D3.Shape.prototype);
GameLib.D3.Shape.TriMesh.prototype.constructor = GameLib.D3.Shape.TriMesh;
/**
* Create instance
* @returns {GameLib.D3.Shape.TriMesh}
*/
GameLib.D3.Shape.TriMesh.prototype.createInstance = function() {
this.instance = new CANNON.TriMesh(
this.vertices,
this.indices
);
GameLib.D3.Shape.prototype.createInstance.call(this);
};
/**
* Update instance
*/
GameLib.D3.Shape.TriMesh.prototype.updateInstance = function() {
this.instance.vertices = this.vertices;
this.instance.indices = this.indices;
this.instance.updateAABB();
this.instance.updateBoundingSphereRadius();
this.instance.updateEdges();
this.instance.updateNormals();
this.instance.updateTree();
};
/**
* Skeleton Superset
* @constructor
* @param graphics GameLib.D3.Graphics
* @param apiSkeleton GameLib.D3.API.Skeleton
*/
GameLib.D3.Skeleton = function Skeleton(
graphics,
apiSkeleton
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiSkeleton)) {
apiSkeleton = {};
}
if (apiSkeleton instanceof GameLib.D3.Skeleton) {
return apiSkeleton;
}
GameLib.D3.API.Skeleton.call(
this,
apiSkeleton.id,
apiSkeleton.name,
apiSkeleton.bones,
apiSkeleton.boneInverses,
apiSkeleton.useVertexTexture,
apiSkeleton.boneTextureWidth,
apiSkeleton.boneTextureHeight,
apiSkeleton.boneMatrices,
apiSkeleton.boneTexture,
apiSkeleton.parentEntity
);
this.bones = this.bones.map(
function(apiBone) {
if (apiBone instanceof GameLib.D3.API.Bone) {
return new GameLib.D3.Bone(
this.graphics,
apiBone
)
} else {
console.warn('apiBone not an instance of API.Bone');
throw new Error('apiBone not an instance of API.Bone');
}
}.bind(this)
);
this.boneInverses = this.boneInverses.map(
function(boneInverse) {
if (boneInverse instanceof GameLib.API.Matrix4) {
return new GameLib.Matrix4(
this.graphics,
boneInverse,
this
);
} else {
console.warn('boneInverse not an instance of API.Matrix4');
throw new Error('boneInverse not an instance of API.Matrix4');
}
}.bind(this)
);
this.boneMatrices = this.boneMatrices.map(
function(boneMatrices) {
if (boneMatrices instanceof GameLib.API.Matrix4) {
return new GameLib.Matrix4(
this.graphics,
boneMatrices,
this
);
} else {
console.warn('boneMatrices not an instance of API.Matrix4');
throw new Error('boneMatrices not an instance of API.Matrix4');
}
}.bind(this)
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_SKELETON,
{
'bones' : [GameLib.D3.Bone]
}
);
};
GameLib.D3.Skeleton.prototype = Object.create(GameLib.D3.API.Skeleton.prototype);
GameLib.D3.Skeleton.prototype.constructor = GameLib.D3.Skeleton;
/**
* Creates an instance skeleton
* @param update boolean
*/
GameLib.D3.Skeleton.prototype.createInstance = function(update) {
var boneInstances = this.bones.map (
function (bone) {
if (GameLib.Utils.UndefinedOrNull(bone)) {
throw new Error('no bone');
}
if (GameLib.Utils.UndefinedOrNull(bone.instance)) {
throw new Error('no bone instance');
}
return bone.instance;
}
);
var parentBoneInstance = this.bones.reduce(
function (result, bone) {
if (result) {
return result;
}
if (bone.parentBoneIds.length === 0) {
return bone.instance;
}
return null;
},
null
);
if (GameLib.Utils.UndefinedOrNull(parentBoneInstance)) {
throw new Error('could not find parent bone instance');
}
this.instance = new THREE.Skeleton(boneInstances);
this.rootBoneInstance = parentBoneInstance;
this.instance.useVertexTexture = this.useVertexTexture;
this.boneIdToBone = {};
this.bones.map(
function (bone) {
this.boneIdToBone[bone.id] = bone;
}.bind(this)
);
/**
* TODO: check if this code does what its supposed to
*/
this.bones.map(
function (__parentBoneInstance) {
return function(bone) {
bone.childBoneIds.map(
function (childBoneId) {
__parentBoneInstance.add(this.boneIdToBone[childBoneId].instance);
}.bind(this)
);
};
}(parentBoneInstance).bind(this)
);
this.instance.update();
this.instance.calculateInverses();
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance
*/
GameLib.D3.Skeleton.prototype.updateInstance = function() {
};
/**
* Converts a GameLib.D3.Skeleton to GameLib.D3.API.Skeleton
* @returns {GameLib.D3.API.Skeleton}
*/
GameLib.D3.Skeleton.prototype.toApiObject = function() {
var apiSkeleton = new GameLib.D3.API.Skeleton(
this.id,
this.name,
this.bones.map(
function (bone) {
return bone.toApiObject();
}
),
this.boneInverses.map(
function (boneInverse) {
return boneInverse.toApiObject();
}
),
this.useVertexTexture,
this.boneTextureWidth,
this.boneTextureHeight,
this.boneMatrices.map(
function (boneMatrix) {
return boneMatrix.toApiObject();
}
),
this.boneTexture,
this.parentEntity
);
return apiSkeleton;
};
/**
* Returns a GameLib.D3.Skeleton from a skeleton Object
* @param graphics GameLib.D3.Graphics
* @param objectSkeleton Object
* @returns {GameLib.D3.Skeleton}
* @constructor
*/
GameLib.D3.Skeleton.FromObject = function(
graphics,
objectSkeleton
) {
if (!objectSkeleton) {
return null;
}
var apiSkeleton = GameLib.D3.API.Skeleton.FromObject(objectSkeleton);
var skeleton = new GameLib.D3.Skeleton(
graphics,
apiSkeleton
);
return skeleton;
};
/**
* Solver Runtime
* @param physics GameLib.D3.Graphics
* @param apiSolver GameLib.D3.API.Solver
* @constructor
*/
GameLib.D3.Solver = function (
physics,
apiSolver
) {
this.physics = physics;
this.physics.isNotCannonThrow();
if (GameLib.Utils.UndefinedOrNull(apiSolver)) {
apiSolver = {};
}
if (apiSolver instanceof GameLib.D3.Solver) {
return apiSolver;
}
GameLib.D3.API.Solver.call(
this,
apiSolver.id,
apiSolver.name,
apiSolver.solverType,
apiSolver.iterations,
apiSolver.tolerance,
apiSolver.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_SOLVER
);
};
GameLib.D3.Solver.prototype = Object.create(GameLib.D3.API.Solver.prototype);
GameLib.D3.Solver.prototype.constructor = GameLib.D3.Solver;
/**
*
* @returns {*}
*/
GameLib.D3.Solver.prototype.createInstance = function() {
if (this.solverType === GameLib.D3.Solver.GS_SOLVER) {
this.instance = new CANNON.GSSolver();
} else if (this.solverType === GameLib.D3.Solver.SPLIT_SOLVER) {
this.instance = new CANNON.SplitSolver();
} else {
throw new Error('unsupported solver type: ' + this.solverType);
}
this.instance.tolerance = this.tolerance;
this.instance.iterations = this.iterations;
GameLib.Component.prototype.createInstance.call(this);
};
/**
*
*/
GameLib.D3.Solver.prototype.updateInstance = function() {
if (this.solverType === GameLib.D3.Solver.GS_SOLVER) {
if (!(this.instance instanceof CANNON.GSSolver)) {
this.instance = new CANNON.GSSolver();
}
}
if (this.solverType === GameLib.D3.Solver.SPLIT_SOLVER) {
if (!(this.instance instanceof CANNON.SplitSolver)) {
this.instance = new CANNON.SplitSolver();
}
}
this.instance.iterations = this.iterations;
this.instance.tolerance = this.tolerance;
};
/**
* GameLib.D3.Solver to GameLib.D3.API.Solver
* @returns {GameLib.D3.API.Solver}
*/
GameLib.D3.Solver.prototype.toApiObject = function() {
var apiSolver = new GameLib.D3.API.Solver(
this.id,
this.name,
this.solverType,
this.iterations,
this.tolerance,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiSolver;
};
/**
* GameLib.D3.Solver from Object Solver
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.Solver}
* @constructor
*/
GameLib.D3.Solver.FromObject = function(graphics, objectComponent) {
var apiSolver = GameLib.D3.API.Solver.FromObject(objectComponent);
return new GameLib.D3.Solver(
graphics,
apiSolver
);
};
/**
* Solver Types
* @type {number}
*/
GameLib.D3.Solver.GS_SOLVER = 0x1;
GameLib.D3.Solver.SPLIT_SOLVER = 0x2;
/**
* Spline constructor
* @param graphics GameLib.D3.Graphics
* @param apiSpline GameLib.D3.API.Spline
* @constructor
*/
GameLib.D3.Spline = function (
graphics,
apiSpline
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiSpline)) {
apiSpline = {};
}
if (apiSpline instanceof GameLib.D3.Spline) {
return apiSpline;
}
GameLib.D3.API.Spline.call(
this,
apiSpline.id,
apiSpline.name,
apiSpline.vertices,
apiSpline.parentEntity
);
this.vertices = this.vertices.map(
function (vertex) {
return new GameLib.Vector3(
graphics,
vertex,
this
)
}
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_SPLINE
);
};
GameLib.D3.Spline.prototype = Object.create(GameLib.D3.API.Spline.prototype);
GameLib.D3.Spline.prototype.constructor = GameLib.D3.Spline;
/**
* Creates an instance spline
*/
GameLib.D3.Spline.prototype.createInstance = function() {
var vertices = this.vertices.map(
function (vertex) {
if (GameLib.Utils.UndefinedOrNull(vertex)) {
throw new Error('no vertex')
}
if (GameLib.Utils.UndefinedOrNull(vertex.instance)) {
throw new Error('no vertex instance')
}
return vertex.instance;
}
);
this.instance = THREE.CatmullRomCurve3(vertices);
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance
*/
GameLib.D3.Spline.prototype.updateInstance = function() {
var vertices = this.vertices.map(
function (vertex) {
if (GameLib.Utils.UndefinedOrNull(vertex)) {
throw new Error('no vertex')
}
if (GameLib.Utils.UndefinedOrNull(vertex.instance)) {
throw new Error('no vertex instance')
}
return vertex.instance;
}
);
this.instance = new THREE.CatmullRomCurve3(vertices);
};
/**
* Converts a GameLib.D3.Spline to GameLib.D3.API.Spline
* @returns {GameLib.D3.API.Spline}
*/
GameLib.D3.Spline.prototype.toApiObject = function() {
return new GameLib.D3.API.Spline(
this.id,
this.name,
this.vertices.map(
function (vertex) {
return vertex.toApiObject()
}
),
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Returns a GameLib.D3.Spline from a spline Object
* @param graphics GameLib.D3.Graphics
* @param objectComponent Object
* @returns {GameLib.D3.Spline}
* @constructor
*/
GameLib.D3.Spline.FromObject = function(
graphics,
objectComponent
) {
var apiSpline = GameLib.D3.API.Spline.FromObject(objectComponent);
return new GameLib.D3.Spline(
graphics,
apiSpline
);
};
/**
* Gets the current point from the spline at the proper value
* @param proper Number (fraction between 0 and 1 indicating position on spline)
* @returns {*}
*/
GameLib.D3.Spline.prototype.getPointAt = function(proper) {
var point = this.instance.getPointAt(proper);
return new GameLib.Vector3(
this.graphics,
new GameLib.API.Vector3(point.x, point.y, point.z),
this,
0.1
);
};
/**
* Stats component for displaying some render statistics (framerate, memory consumption, etc)
* @param stats
* @param id
* @param name
* @param domElement
* @param parentEntity
* @constructor
*/
GameLib.D3.Stats = function(
stats,
id,
name,
domElement,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(stats)) {
throw new Error('Need Stats object')
}
this.stats = stats;
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'Stats (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(domElement)) {
console.warn('Need a DOM element for stats');
throw new Error('Need a DOM element for stats');
}
this.domElement = domElement;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_STATS,
{
'domElement': GameLib.DomElement
}
);
};
GameLib.D3.Stats.prototype = Object.create(GameLib.Component.prototype);
GameLib.D3.Stats.prototype.constructor = GameLib.D3.Stats;
GameLib.D3.Stats.prototype.resize = function() {
console.log('override stats resize per implementation');
};
/**
* Creates a helper instance
*/
GameLib.D3.Stats.prototype.createInstance = function() {
this.instance = this.stats();
this.resize();
this.domElement.instance.parentElement.appendChild(this.instance.dom);
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Stats.prototype.updateInstance = function() {
this.instance = new this.stats();
};
GameLib.D3.Stats.prototype.start = function() {
this.instance.begin();
};
GameLib.D3.Stats.prototype.end = function() {
this.instance.end();
};
/**
* Texture Superset - The apiTexture properties get moved into the Texture object itself, and then the instance is
* created
* @param apiTexture
* @param graphics GameLib.D3.Graphics
* @constructor
*/
GameLib.D3.Texture = function(
graphics,
apiTexture
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiTexture)) {
apiTexture = {};
}
if (apiTexture instanceof GameLib.D3.Texture) {
return apiTexture;
}
GameLib.D3.API.Texture.call(
this,
apiTexture.id,
apiTexture.typeId,
apiTexture.name,
apiTexture.image,
apiTexture.images,
apiTexture.wrapS,
apiTexture.wrapT,
apiTexture.repeat,
apiTexture.data,
apiTexture.format,
apiTexture.mapping,
apiTexture.magFilter,
apiTexture.minFilter,
apiTexture.textureType,
apiTexture.anisotropy,
apiTexture.offset,
apiTexture.generateMipmaps,
apiTexture.flipY,
apiTexture.mipmaps,
apiTexture.unpackAlignment,
apiTexture.premultiplyAlpha,
apiTexture.encoding,
apiTexture.canvas,
apiTexture.animated,
apiTexture.reverseAnimation,
apiTexture.forward,
apiTexture.parentEntity
);
this.offset = new GameLib.Vector2(
this.graphics,
this.offset,
this
);
this.repeat = new GameLib.Vector2(
this.graphics,
this.repeat,
this
);
if (this.image instanceof GameLib.D3.API.Image) {
this.image = new GameLib.D3.Image(
this.graphics,
this.image
);
}
this.images = this.images.map(
function(image) {
if (image instanceof GameLib.D3.API.Image) {
return new GameLib.D3.Image(
this.graphics,
image
);
} else {
return image;
}
}.bind(this)
);
if (this.canvas instanceof GameLib.D3.API.Canvas) {
this.canvas = new GameLib.D3.Canvas(
this.graphics,
this.canvas
);
}
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_TEXTURE,
{
'image' : GameLib.D3.Image,
'images' : [GameLib.D3.Image],
'canvas' : GameLib.D3.Canvas
}
);
};
GameLib.D3.Texture.prototype = Object.create(GameLib.D3.API.Texture.prototype);
GameLib.D3.Texture.prototype.constructor = GameLib.D3.Texture;
/**
* Texture Formats
* @type {number}
*/
GameLib.D3.Texture.TYPE_ALPHA_FORMAT = 1019;
GameLib.D3.Texture.TYPE_RGB_FORMAT = 1020;
GameLib.D3.Texture.TYPE_RGBA_FORMAT = 1021;
GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT = 1022;
GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT = 1023;
GameLib.D3.Texture.TYPE_DEPTH_FORMAT = 1026;
/**
* Mapping modes
* @type {number}
*/
GameLib.D3.Texture.TYPE_UV_MAPPING = 300;
GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING = 301;
GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING = 302;
GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING = 303;
GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING = 304;
GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING = 305;
GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING = 306;
GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING = 307;
/**
* Wrapping Modes
* @type {number}
*/
GameLib.D3.Texture.TYPE_REPEAT_WRAPPING = 1000;
GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING = 1001;
GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING = 1002;
/**
* Mipmap Filters
* @type {number}
*/
GameLib.D3.Texture.TYPE_NEAREST_FILTER = 1003;
GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER = 1004;
GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER = 1005;
GameLib.D3.Texture.TYPE_LINEAR_FILTER = 1006;
GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER = 1007;
GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER = 1008;
/**
* Texture Data Types
* @type {number}
*/
GameLib.D3.Texture.TYPE_UNSIGNED_BYTE = 1009;
GameLib.D3.Texture.TYPE_BYTE = 1010;
GameLib.D3.Texture.TYPE_SHORT = 1011;
GameLib.D3.Texture.TYPE_UNSIGNED_SHORT = 1012;
GameLib.D3.Texture.TYPE_INT = 1013;
GameLib.D3.Texture.TYPE_UNSIGNED_INT = 1014;
GameLib.D3.Texture.TYPE_FLOAT = 1015;
GameLib.D3.Texture.TYPE_HALF_FLOAT = 1025;
/**
* Encoding Modes
* @type {number}
*/
GameLib.D3.Texture.TYPE_LINEAR_ENCODING = 3000; // NO ENCODING AT ALL.
GameLib.D3.Texture.TYPE_SRGB_ENCODING = 3001;
GameLib.D3.Texture.TYPE_GAMMA_ENCODING = 3007; // USES GAMMA_FACTOR, FOR BACKWARDS COMPATIBILITY WITH WEBGLRENDERER.GAMMAINPUT/GAMMAOUTPUT
GameLib.D3.Texture.TYPE_RGBE_ENCODING = 3002; // AKA RADIANCE.
GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING = 3003;
GameLib.D3.Texture.TYPE_RGBM7_ENCODING = 3004;
GameLib.D3.Texture.TYPE_RGBM16_ENCODING = 3005;
GameLib.D3.Texture.TYPE_RGBD_ENCODING = 3006; // MAXRANGE IS 256.
GameLib.D3.Texture.TEXTURE_TYPE_NORMAL = 0x1;
GameLib.D3.Texture.TEXTURE_TYPE_CUBE = 0x2;
GameLib.D3.Texture.TEXTURE_TYPE_CANVAS = 0x3;
/**
* Creates an instance of our texture object
* @returns {*}
*/
GameLib.D3.Texture.prototype.createInstance = function() {
if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_CUBE) {
if (this.images.length !== 6) {
throw new Error('not enough images for cube texture');
}
var imageInstances = this.images.map(
function(image) {
if (GameLib.Utils.UndefinedOrNull(image)) {
throw new Error('no image');
}
if (GameLib.Utils.UndefinedOrNull(image.instance)) {
throw new Error('no image instance');
}
return image.instance
}
);
this.instance = new THREE.CubeTexture(imageInstances);
} else if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_NORMAL) {
if (
GameLib.Utils.UndefinedOrNull(this.image) ||
GameLib.Utils.UndefinedOrNull(this.image.instance)
) {
this.instance = new THREE.Texture();
} else {
//if (GameLib.Utils.UndefinedOrNull(this.image.instance)) {
// throw new Error('no image instance');
//}
this.instance = new THREE.Texture(
this.image.instance
);
}
} else if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_CANVAS) {
if (GameLib.Utils.UndefinedOrNull(this.canvas)) {
this.instance = new THREE.Texture();
} else {
if (GameLib.Utils.UndefinedOrNull(this.canvas.instance)) {
throw new Error('no canvas instance');
}
this.instance = new THREE.Texture(
this.canvas.instance
);
}
}
/**
* Some settings we copy from the instance
*/
this.mapping = this.instance.mapping;
this.encoding = this.instance.encoding;
this.format = this.instance.format;
/**
* Others we apply to the instance
*/
this.instance.name = this.name;
this.instance.flipY = this.flipY;
this.instance.offset.x = this.offset.x;
this.instance.offset.y = this.offset.y;
this.instance.repeat.x = this.repeat.x;
this.instance.repeat.y = this.repeat.y;
this.instance.wrapS = this.wrapS;
this.instance.wrapT = this.wrapT;
this.instance.needsUpdate = true;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.D3.Texture.prototype.updateInstance = function(property) {
if (GameLib.Utils.UndefinedOrNull(this.instance)) {
try {
this.createInstance();
return;
} catch (error) {
console.error(error);
}
}
if (GameLib.Utils.UndefinedOrNull(property)) {
throw new Error('need to specify a property');
}
if (property === 'image') {
if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_NORMAL) {
if (
GameLib.Utils.UndefinedOrNull(this.image) &&
this.instance.image
) {
try {
this.createInstance();
} catch (error) {
console.error(error);
}
}
if (this.image && this.image.instance && this.instance.image !== this.image.instance) {
try {
this.createInstance();
} catch (error) {
console.error(error);
}
}
} else if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_CANVAS) {
if (
GameLib.Utils.UndefinedOrNull(this.canvas) &&
this.instance.canvas
) {
try {
this.createInstance();
} catch (error) {
console.error(error);
}
}
if (this.canvas && this.canvas.instance && this.instance.image !== this.canvas.instance) {
try {
this.createInstance();
} catch (error) {
console.error(error);
}
}
} else if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_CUBE) {
console.log('todo : cube images change check here');
}
this.publish(
GameLib.Event.IMAGE_CHANGED,
{
texture : this
}
);
this.instance.needsUpdate = true;
}
if (property === 'name') {
this.instance.name = this.name;
}
if (property === 'flipY') {
this.instance.flipY = this.flipY;
}
if (property === 'encoding') {
this.instance.encoding = this.encoding;
}
if (property === 'offset') {
this.instance.offset.x = this.offset.x;
this.instance.offset.y = this.offset.y;
}
if (property === 'repeat') {
this.instance.repeat.x = this.repeat.x;
this.instance.repeat.y = this.repeat.y;
}
if (property === 'mapping') {
this.instance.mapping = this.mapping;
}
if (property === 'format') {
this.instance.format = this.format;
}
if (property === 'wrapS') {
this.instance.wrapS = this.wrapS;
}
if (property === 'wrapT') {
this.instance.wrapT = this.wrapT;
}
if (property === 'animated') {
GameLib.Event.Emit(
GameLib.Event.TEXTURE_ANIMATED_CHANGE,
{
texture : this
}
)
}
};
/**
* Converts a GameLib.D3.Texture to a GameLib.D3.API.Texture
* @returns {GameLib.D3.API.Texture}
*/
GameLib.D3.Texture.prototype.toApiObject = function() {
var apiTexture = new GameLib.D3.API.Texture(
this.id,
this.typeId,
this.name,
GameLib.Utils.IdOrNull(this.image),
this.images.map(
function(image) {
return GameLib.Utils.IdOrNull(image)
}
),
this.wrapS,
this.wrapT,
this.repeat.toApiObject(),
this.data,
this.format,
this.mapping,
this.magFilter,
this.minFilter,
this.textureType,
this.anisotropy,
this.offset.toApiObject(),
this.generateMipmaps,
this.flipY,
this.mipmaps,
this.unpackAlignment,
this.premultiplyAlpha,
this.encoding,
GameLib.Utils.IdOrNull(this.canvas),
this.animated,
this.reverseAnimation,
this.forward,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiTexture;
};
/**
* Converts from an Object texture to a GameLib.D3.Texture
* @param graphics GameLib.D3.Graphics
* @param objectTexture Object
* @constructor
*/
GameLib.D3.Texture.FromObject = function(
graphics,
objectTexture
) {
var apiTexture = GameLib.D3.API.Texture.FromObject(objectTexture);
return new GameLib.D3.Texture(
graphics,
apiTexture
);
};
/**
* TriangleEdge
* @param triangle
* @param edge
* @constructor
*/
GameLib.D3.TriangleEdge = function(
triangle,
edge
) {
this.triangle = triangle;
this.edge = edge;
};
/**
* Runtime Vertex
* @constructor
* @param implementation
* @param apiVertex
*/
GameLib.D3.Vertex = function Vertex(
implementation,
apiVertex
) {
this.implementation = implementation;
if (implementation instanceof GameLib.D3.Graphics) {
this.implementation.isNotThreeThrow();
} else if (implementation instanceof GameLib.D3.Physics) {
this.implementation.isNotCannonThrow();
} else {
throw new Error('Unhandled implementation : ' + implementation);
}
if (GameLib.Utils.UndefinedOrNull(apiVertex)) {
apiVertex = {};
}
if (apiVertex instanceof GameLib.D3.Vertex) {
return apiVertex;
}
GameLib.D3.API.Vertex.call(
this,
apiVertex.position,
apiVertex.boneWeights
);
this.position = new GameLib.Vector3(
this.implementation,
this.position,
null
);
if (implementation instanceof GameLib.D3.Graphics) {
this.boneWeights = this.boneWeights.map(
function(apiBoneWeight) {
return new GameLib.D3.BoneWeight(
this.implementation,
apiBoneWeight
)
}.bind(this)
)
}
};
GameLib.D3.Vertex.prototype = Object.create(GameLib.D3.API.Vertex.prototype);
GameLib.D3.Vertex.prototype.constructor = GameLib.D3.Vertex;
/**
* Converts a GameLib.D3.Vertex to GameLib.D3.API.Vertex
* @returns {GameLib.D3.API.Vertex}
*/
GameLib.D3.Vertex.prototype.toApiObject = function() {
return new GameLib.D3.API.Vertex(
this.position.toApiObject(),
this.boneWeights.map(function(boneWeight){
return boneWeight.toApiObject();
})
);
};
/**
* Returns a GameLib.D3.Vertex from a vertex Object
* @param implementation (graphics or physics object)
* @param objectVertex Object
* @returns {GameLib.D3.Vertex}
* @constructor
*/
GameLib.D3.Vertex.FromObject = function(
implementation,
objectVertex
) {
var apiVertex = GameLib.D3.API.Vertex.FromObject(objectVertex);
return new GameLib.D3.Vertex(
implementation,
apiVertex
);
};
/**
* Viewport Runtime
* @param graphics GameLib.D3.Graphics
* @param apiViewport GameLib.D3.API.Viewport
* @constructor
*/
GameLib.D3.Viewport = function (
graphics,
apiViewport
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiViewport)) {
apiViewport = {};
}
if (apiViewport instanceof GameLib.D3.Viewport) {
return apiViewport;
}
GameLib.D3.API.Viewport.call(
this,
apiViewport.id,
apiViewport.name,
apiViewport.width,
apiViewport.height,
apiViewport.x,
apiViewport.y,
apiViewport.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_VIEWPORT
);
};
GameLib.D3.Viewport.prototype = Object.create(GameLib.D3.API.Viewport.prototype);
GameLib.D3.Viewport.prototype.constructor = GameLib.D3.Viewport;
/**
*
* @returns {boolean}
*/
GameLib.D3.Viewport.prototype.createInstance = function() {
this.instance = true;
GameLib.Component.prototype.createInstance.call(this);
};
/**
*
*/
GameLib.D3.Viewport.prototype.updateInstance = function() {
};
/**
* GameLib.D3.Viewport to GameLib.D3.API.Viewport
* @returns {GameLib.D3.API.Viewport}
*/
GameLib.D3.Viewport.prototype.toApiObject = function() {
var apiViewport = new GameLib.D3.API.Viewport(
this.id,
this.name,
this.width,
this.height,
this.x,
this.y,
GameLib.Utils.IdOrNull(this.parentEntity)
);
return apiViewport;
};
/**
* GameLib.D3.Viewport from Object Viewport
* @param graphics
* @param objectComponent
* @returns {GameLib.D3.Viewport}
* @constructor
*/
GameLib.D3.Viewport.FromObject = function(graphics, objectComponent) {
var apiViewport = GameLib.D3.API.Viewport.FromObject(objectComponent);
return new GameLib.D3.Viewport(
graphics,
apiViewport
);
};
/**
* Runtime domElement for updating instance objects
* @param apiDomElement GameLib.API.DomElement
* @constructor
*/
GameLib.DomElement = function (apiDomElement) {
if (GameLib.Utils.UndefinedOrNull(apiDomElement)) {
apiDomElement = {};
}
if (apiDomElement instanceof GameLib.DomElement) {
return apiDomElement;
}
GameLib.API.DomElement.call(
this,
apiDomElement.id,
apiDomElement.name,
apiDomElement.domElementId,
apiDomElement.parentEntity
);
this.fullscreen = false;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_DOM_ELEMENT
);
};
GameLib.DomElement.prototype = Object.create(GameLib.API.DomElement.prototype);
GameLib.DomElement.prototype.constructor = GameLib.DomElement;
/**
* Creates an instance domElement
* @returns {*}
*/
GameLib.DomElement.prototype.createInstance = function() {
this.instance = document.getElementById(this.domElementId);
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates instance domElement
*/
GameLib.DomElement.prototype.updateInstance = function() {
this.instance = document.getElementById(this.domElementId);
};
/**
* Converts runtime DomElement to API DomElement
* @returns {GameLib.API.DomElement}
*/
GameLib.DomElement.prototype.toApiObject = function() {
return new GameLib.API.DomElement(
this.id,
this.name,
this.domElementId,
GameLib.Utils.IdOrNull(this.parentEntity)
);
};
/**
* Appends domInstance to DOM instance
* @param domInstance
*/
GameLib.DomElement.prototype.append = function(domInstance) {
this.instance.appendChild(domInstance);
};
/**
* Clears DOM instance
*/
GameLib.DomElement.prototype.clear = function() {
this.instance.innerHTML = '';
};
GameLib.DomElement.prototype.requestFullscreen = function(event) {
var docEl = document.documentElement;
if (docEl.requestFullscreen) {
docEl.requestFullscreen();
} else if (docEl.msRequestFullscreen) {
docEl.msRequestFullscreen();
} else if (docEl.mozRequestFullScreen) {
docEl.mozRequestFullScreen();
} else if (docEl.webkitRequestFullscreen) {
docEl.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
}
this.fullscreen = true;
};
GameLib.DomElement.prototype.exitFullscreen = function(event) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
this.fullscreen = false;
};
GameLib.DomElement.FromObject = function(objectDom) {
var apiDomElement = GameLib.API.DomElement.FromObject(objectDom);
var domElement = new GameLib.DomElement(
apiDomElement
);
return domElement;
};
/**
* Runtime Dom
* @constructor
* @param document DOM Document
* @param window DOM Window
*/
GameLib.Dom = function(
document,
window
) {
this.document = document;
this.window = window;
};
/**
* GameLib.EntityManager
* @constructor
*/
GameLib.EntityManager = function(apiEntityManager) {
if (GameLib.Utils.UndefinedOrNull(apiEntityManager)) {
apiEntityManager = {};
}
if (apiEntityManager instanceof GameLib.EntityManager) {
return apiEntityManager;
}
GameLib.API.EntityManager.call(
this,
apiEntityManager.id,
apiEntityManager.name,
apiEntityManager.entities,
apiEntityManager.defaultEntity,
apiEntityManager.defaultRenderer
);
/**
* The 'register' array is a register of each component currently loaded - when the linking
* system starts it also loads all the current components from the entity manager
* @type {Array}
*/
this.register = [];
GameLib.Event.Subscribe(
GameLib.Event.COMPONENT_REGISTER,
this.registerComponent.bind(this)
);
GameLib.Event.Subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent.bind(this)
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_ENTITY_MANAGER,
{
'entities' : [GameLib.Entity],
'defaultEntity' : GameLib.Entity,
'defaultRenderer' : GameLib.D3.Renderer
}
);
};
GameLib.EntityManager.prototype = Object.create(GameLib.API.EntityManager.prototype);
GameLib.EntityManager.prototype.constructor = GameLib.EntityManager;
GameLib.EntityManager.prototype.createInstance = function() {
this.instance = GameLib.EntityManager.Instance;
GameLib.Component.prototype.createInstance.call(this);
};
GameLib.EntityManager.prototype.registerComponent = function(data) {
var length = this.register.length;
GameLib.Utils.PushUnique(this.register, data.component);
if (length !== this.register.length) {
GameLib.Event.Emit(
GameLib.Event.REGISTER_UPDATE,
{
register : this.register
}
);
}
};
GameLib.EntityManager.prototype.removeComponent = function(data) {
var index = this.register.indexOf(data.component);
if (index !== -1) {
this.register.splice(index, 1);
GameLib.Event.Emit(
GameLib.Event.REGISTER_UPDATE,
{
register : this.register
}
);
}
};
/**
* Creates an GameLib.Entity and adds it to entities array
* @returns {*}
*/
GameLib.EntityManager.prototype.createEntity = function(name) {
var apiEntity = new GameLib.API.Entity(
null,
name,
null,
null,
this
);
var entity = new GameLib.Entity(
apiEntity
);
this.entities.push(entity);
this.defaultEntity = entity;
GameLib.Event.Emit(
GameLib.Event.NEW_ENTITY,
{
entity : entity
}
);
return entity;
};
/**
* Returns an entity by ID or null
* @param id
* @returns {*}
*/
GameLib.EntityManager.prototype.findEntityById = function(id) {
return this.entities.reduce(
function(result, entity){
if (entity.id === id) {
result = entity;
}
return result;
},
null
);
};
GameLib.EntityManager.prototype.findComponentById = function(id) {
return this.register.reduce(
function(result, component){
if (component.id === id){
result = component;
}
return result;
},
null
);
};
GameLib.EntityManager.prototype.findHelperByObject = function(object) {
return this.register.reduce(
function(result, component) {
if (component instanceof GameLib.D3.Helper) {
if (component.object === object) {
result = component;
}
}
return result;
},
null
);
};
GameLib.EntityManager.prototype.findSceneByObject = function(object) {
return this.register.reduce(
function(result, component) {
if (component instanceof GameLib.D3.Scene) {
if (component.meshes.indexOf(object) !== -1) {
result = component;
}
if (component.lights.indexOf(object) !== -1) {
result = component;
}
}
return result;
},
null
);
};
/**
* Adds an entity to this manager
* @param entity GameLib.Entity
*/
GameLib.EntityManager.prototype.addEntity = function(entity) {
entity.parentEntityManager = this;
this.entities.push(entity);
};
/**
* Returns entity by name
* @param name
* @returns {*}
*/
GameLib.EntityManager.prototype.queryByName = function(name) {
return this.entities.reduce(
function(result, entity){
if (entity.name === name) {
result = entity;
}
return result;
},
null
)
};
/**
* Removes an entity - do we remove all its components as well?
* @param entity GameLib.D3.Entity
* @returns boolean true if successful
*/
GameLib.EntityManager.prototype.removeEntity = function(entity) {
var index = this.entities.indexOf(entity);
if (index === -1) {
console.log('failed to remove entity : ', entity);
return false;
}
this.entities.splice(index, 1);
entity.parentEntityManager = null;
return true;
};
/**
* Returns all the entities with the following components
* @param components GameLib.Component[]
*/
GameLib.EntityManager.prototype.findEntities = function(components) {
var entities = this.entities.reduce(
function(result, entity) {
var hasAllComponents = components.reduce(
function(componentResult, component) {
if (!entity.hasComponent(component)) {
componentResult = false;
}
return componentResult;
},
true
);
if (hasAllComponents) {
result.push(entity);
}
return result;
},
[]
);
return entities;
};
/**
* Returns all actual components of all entities that contain this component
* @param constructors (array of constructor or just a single constructor)
*/
GameLib.EntityManager.prototype.queryComponents = function(constructors) {
return this.register.reduce(
function(result, component) {
if (constructors instanceof Array) {
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;
},
[]
);
};
/**
* Converts a GameLib.Entity to GameLib.API.Entity
* @returns {GameLib.API.EntityManager}
*/
GameLib.EntityManager.prototype.toApiObject = function() {
var apiEntities = this.entities.map(
function (entity) {
return GameLib.Utils.IdOrNull(entity);
}
);
var apiEntityManager = new GameLib.API.EntityManager(
this.id,
this.name,
apiEntities,
GameLib.Utils.IdOrNull(this.defaultEntity),
GameLib.Utils.IdOrNull(this.defaultRenderer)
);
return apiEntityManager;
};
/**
* Returns an EntityManager from an Object entity manager
* @param objectEntityManager Object
* @constructor
*/
GameLib.EntityManager.FromObject = function(objectEntityManager) {
var apiEntityManager = GameLib.API.EntityManager.FromObject(objectEntityManager);
var entityManager = new GameLib.EntityManager(apiEntityManager);
return entityManager;
};
/**
* Runtime Entity
* @param apiEntity GameLib.D3.API.Entity
* @constructor
*/
GameLib.Entity = function (
apiEntity
) {
if (GameLib.Utils.UndefinedOrNull(apiEntity)) {
apiEntity = {};
}
if (apiEntity instanceof GameLib.Entity) {
return apiEntity;
}
GameLib.API.Entity.call(
this,
apiEntity.id,
apiEntity.name,
apiEntity.components,
apiEntity.parentEntity,
apiEntity.parentEntityManager
);
this.componentToCreate = 0;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_ENTITY,
{
'components' : [GameLib.Component],
'activeComponent' : GameLib.Component
}
);
};
GameLib.Entity.prototype = Object.create(GameLib.API.Entity.prototype);
GameLib.Entity.prototype.constructor = GameLib.Entity;
/**
* Creates an entity instance
*/
GameLib.Entity.prototype.createInstance = function() {
/**
* FUCK ecsjs and tiny-ecs - no client-side support and shitty code (only takes constructors as args)
*/
this.instance = true;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Adds a component to this entity through the instance (should notify the entity manager instance)
* @param component
*/
GameLib.Entity.prototype.addComponent = function(component) {
GameLib.Utils.PushUnique(this.components, component);
if (component instanceof GameLib.D3.Mesh) {
/**
* For meshes, simply get the children components
* @type {Array}
*/
component.getChildrenComponents().map(function(childComponent){
GameLib.Utils.PushUnique(this.components, childComponent);
childComponent.parentEntity = this;
}.bind(this))
} else {
/**
* Here we will dig into this component - find all its 'parentEntity' members - and update them accordingly
*/
component.buildIdToObject();
/**
* Also add the child components of this component as components of this entity
*/
for (var property in component.idToObject) {
if (component.idToObject.hasOwnProperty(property) &&
component.idToObject[property] !== component &&
component.idToObject[property] instanceof GameLib.Component
) {
GameLib.Utils.PushUnique(this.components, component.idToObject[property]);
component.idToObject[property].parentEntity = this;
}
}
}
/**
* Finally, we are the boss component - update my parent entity
* @type {GameLib.Entity}
*/
component.parentEntity = this;
};
/**
* Returns all components of type 'constructor'
* @param constructor
*/
GameLib.Entity.prototype.getComponents = function(constructor) {
var components = this.components.reduce(
function(result, component) {
if (component instanceof constructor) {
result.push(component);
}
return result;
},
[]
);
return components;
};
/**
* Returns the first component or null
* @param constructor
*/
GameLib.Entity.prototype.getFirstComponent = function(constructor) {
var components = this.getComponents(constructor);
if (components.length > 0) {
return components[0];
}
return null;
};
/**
* Returns true when this entity has a certain component, false otherwise
* @param constructor
*/
GameLib.Entity.prototype.hasComponent = function(constructor) {
var has = this.components.reduce(
function(result, component) {
if (component instanceof constructor) {
result = true;
}
return result;
},
false
);
return has;
};
/**
*
* @param component
*/
GameLib.Entity.prototype.removeComponent = function(component) {
if (GameLib.Utils.UndefinedOrNull(component)) {
component = this.activeComponent;
}
var childIndex = this.components.indexOf(component);
if (childIndex !== -1) {
this.components.splice(childIndex, 1);
} else {
console.error('component not found');
}
/**
* Break the dependency to the parent
*/
component.parentEntity = null;
return true;
};
/**
* Updates an entity instance
*/
GameLib.Entity.prototype.updateInstance = function() {
console.log('entity update instance called');
};
/**
* Converts a GameLib.Entity to GameLib.API.Entity
* @returns {GameLib.API.Entity}
*/
GameLib.Entity.prototype.toApiObject = function() {
var apiComponents = this.components.map(
function(component) {
return GameLib.Utils.IdOrNull(component);
}
);
return new GameLib.API.Entity(
this.id,
this.name,
apiComponents,
GameLib.Utils.IdOrNull(this.parentEntity),
GameLib.Utils.IdOrNull(this.parentEntityManager)
);
};
/**
* Entity from Object
* @param objectEntity Object
* @param parentEntityManager GameLib.D3.EntityManager
* @returns {GameLib.Entity}
* @constructor
*/
GameLib.Entity.FromObject = function(objectEntity, parentEntityManager) {
var apiEntity = GameLib.API.Entity.FromObject(objectEntity);
var entity = new GameLib.Entity(
apiEntity
);
if (GameLib.Utils.UndefinedOrNull(parentEntityManager)) {
return entity;
}
parentEntityManager.addEntity(entity);
return entity;
};
/**
* Stats component for displaying some render statistics (framerate, memory consumption, etc)
* @param gui
* @param id
* @param name
* @param domElement
* @param objects
* @param parentEntity
* @constructor
*/
GameLib.GUI = function(
gui,
id,
name,
domElement,
objects,
parentEntity
) {
if (GameLib.Utils.UndefinedOrNull(gui)) {
throw new Error('Need GUI object')
}
this.gui = gui;
if (GameLib.Utils.UndefinedOrNull(id)) {
id = GameLib.Utils.RandomId();
}
this.id = id;
if (GameLib.Utils.UndefinedOrNull(name)) {
name = 'GUI (' + id + ')';
}
this.name = name;
if (GameLib.Utils.UndefinedOrNull(domElement)) {
console.warn('Need a DOM element for stats');
throw new Error('Need a DOM element for stats');
}
this.domElement = domElement;
if (GameLib.Utils.UndefinedOrNull(objects)) {
objects = [];
}
this.objects = objects;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
this.parentEntity = parentEntity;
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_GUI,
{
'domElement': GameLib.DomElement
}
);
};
GameLib.GUI.prototype = Object.create(GameLib.Component.prototype);
GameLib.GUI.prototype.constructor = GameLib.GUI;
/**
* Creates a helper instance
*/
GameLib.GUI.prototype.createInstance = function() {
this.instance = new dat.GUI( { autoPlace: false } );
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance with the current state
*/
GameLib.GUI.prototype.updateInstance = function() {
this.instance = new dat.GUI( { autoPlace: false } );
};
/**
* Removes empty folders from instance
*/
GameLib.GUI.prototype.removeEmtpyFolders = function() {
this.instance.removeEmptyFolders();
};
/**
* Remove all folders from instance
*/
GameLib.GUI.prototype.removeAllFolders = function() {
this.instance.removeAllFolders();
};
/**
* Adds a folder to instance
* @param folderName
* @returns {*}
*/
GameLib.GUI.prototype.addFolder = function(folderName) {
try {
return this.instance.addFolder(folderName);
} catch (e) {
try {
folderName += ' duplicate (' + GameLib.Utils.RandomId() + ')';
return this.instance.addFolder(folderName);
} catch (e) {
console.log(e.message);
return null;
}
}
};
/**
* Runtime Matrix4
* @param graphics
* @param parentObject
* @param apiMatrix4
* @param grain
* @constructor
*/
GameLib.Matrix4 = function(
graphics,
apiMatrix4,
parentObject,
grain
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMatrix4)) {
apiMatrix4 = {};
}
if (apiMatrix4 instanceof GameLib.Matrix4) {
return apiMatrix4;
}
GameLib.API.Matrix4.call(
this,
apiMatrix4.rows[0],
apiMatrix4.rows[1],
apiMatrix4.rows[2],
apiMatrix4.rows[3]
);
if (GameLib.Utils.UndefinedOrNull(parentObject)) {
parentObject = null;
}
this.parentObject = parentObject;
if (GameLib.Utils.UndefinedOrNull(grain)) {
grain = 0.001;
}
this.grain = grain;
this.rows = this.rows.map(
function(row) {
if (row instanceof GameLib.API.Vector4) {
return new GameLib.Vector4(
this.graphics,
row,
this,
this.grain
);
} else {
console.warn('Attempted conversion of wrong instance');
throw new Error('Attempted conversion of wrong instance');
}
}.bind(this)
);
this.forward = new GameLib.Vector4(
this.graphics,
this.forward,
this,
this.grain
);
this.left = new GameLib.Vector4(
this.graphics,
this.left,
this,
this.grain
);
this.up = new GameLib.Vector4(
this.graphics,
this.up,
this,
this.grain
);
this.createInstance();
};
GameLib.Matrix4.prototype = Object.create(GameLib.API.Matrix4.prototype);
GameLib.Matrix4.prototype.constructor = GameLib.Matrix4;
/**
* Creates a matrix 4 instance (currently from graphics lib)
* @param update
*/
GameLib.Matrix4.prototype.createInstance = function(update) {
this.instance = new THREE.Matrix4();
/**
* We transpose our matrix when we send it to three since we use a different ordering system
* They say they use
*/
this.instance.set(
this.rows[0].x,
this.rows[1].x,
this.rows[2].x,
this.rows[3].x,
this.rows[0].y,
this.rows[1].y,
this.rows[2].y,
this.rows[3].y,
this.rows[0].z,
this.rows[1].z,
this.rows[2].z,
this.rows[3].z,
this.rows[0].w,
this.rows[1].w,
this.rows[2].w,
this.rows[3].w
);
};
/**
* Updates this instance
*/
GameLib.Matrix4.prototype.updateInstance = function() {
this.instance.set(
this.rows[0].x,
this.rows[1].x,
this.rows[2].x,
this.rows[3].x,
this.rows[0].y,
this.rows[1].y,
this.rows[2].y,
this.rows[3].y,
this.rows[0].z,
this.rows[1].z,
this.rows[2].z,
this.rows[3].z,
this.rows[0].w,
this.rows[1].w,
this.rows[2].w,
this.rows[3].w
);
if (this.parentObject &&
this.parentObject.updateInstance) {
this.parentObject.updateInstance();
}
};
/**
* GameLib.Matrix4 to GameLib.API.Matrix4
* @returns {*}
*/
GameLib.Matrix4.prototype.toApiObject = function () {
return new GameLib.API.Matrix4(
this.rows[0].toApiObject(),
this.rows[1].toApiObject(),
this.rows[2].toApiObject(),
this.rows[3].toApiObject()
);
};
/**
* Creates a GameLib.Matrix4 from an Object matrix
* @param graphics GameLib.D3.Graphics
* @param objectMatrix Object
* @param parentObject
* @returns {GameLib.Matrix4}
* @constructor
*/
GameLib.Matrix4.FromObject = function(graphics, objectMatrix, parentObject) {
var apiMatrix = new GameLib.API.Matrix4.FromObject(objectMatrix);
return new GameLib.Matrix4(
graphics,
parentObject,
apiMatrix
)
};
/**
* Lookat
* @param position
* @param target
* @param up
* @returns {GameLib.Matrix4}
*/
GameLib.Matrix4.prototype.lookAt = function (position, target, up) {
var pv = new GameLib.API.Vector3(position.x, position.y, position.z);
var forward = pv.subtract(target).normalize();
if (forward.squared() === 0) {
forward.z = 1;
}
var left = up.cross(forward).normalize();
if (left.squared() === 0) {
forward.x += 0.0001;
left = up.cross(forward).normalize();
}
var _up = forward.cross(left);
this.rows[0].x = left.x;
this.rows[0].y = left.y;
this.rows[0].z = left.z;
this.rows[1].x = _up.x;
this.rows[1].y = _up.y;
this.rows[1].z = _up.z;
this.rows[2].x = forward.x;
this.rows[2].y = forward.y;
this.rows[2].z = forward.z;
this.forward.x = forward.x;
this.forward.y = forward.y;
this.forward.z = forward.z;
this.left.x = left.x;
this.left.y = left.y;
this.left.z = left.z;
this.up.x = _up.x;
this.up.y = _up.y;
this.up.z = _up.z;
this.updateInstance();
return this;
};
/**
* Identity
*/
GameLib.Matrix4.prototype.identity = function () {
this.rows = [
new GameLib.Vector4(
this.graphics,
new GameLib.API.Vector4(1,0,0,0),
this,
this.grain
),
new GameLib.Vector4(
this.graphics,
new GameLib.API.Vector4(0,1,0,0),
this,
this.grain
),
new GameLib.Vector4(
this.graphics,
new GameLib.API.Vector4(0,0,1,0),
this,
this.grain
),
new GameLib.Vector4(
this.graphics,
new GameLib.API.Vector4(0,0,0,1),
this,
this.grain
)
];
};
/**
* Transpose
* @returns {GameLib.Matrix4}
*/
GameLib.Matrix4.prototype.transpose = function () {
this.temp[0].x = this.rows[0].x;
this.temp[0].y = this.rows[1].x;
this.temp[0].z = this.rows[2].x;
this.temp[0].w = this.rows[3].x;
this.temp[1].x = this.rows[0].y;
this.temp[1].y = this.rows[1].y;
this.temp[1].z = this.rows[2].y;
this.temp[1].w = this.rows[3].y;
this.temp[2].x = this.rows[0].z;
this.temp[2].y = this.rows[1].z;
this.temp[2].z = this.rows[2].z;
this.temp[2].w = this.rows[3].z;
this.temp[3].x = this.rows[0].w;
this.temp[3].y = this.rows[1].w;
this.temp[3].z = this.rows[2].w;
this.temp[3].w = this.rows[3].w;
this.rows[0].x = this.temp[0].x;
this.rows[0].y = this.temp[0].y;
this.rows[0].z = this.temp[0].z;
this.rows[0].w = this.temp[0].w;
this.rows[1].x = this.temp[1].x;
this.rows[1].y = this.temp[1].y;
this.rows[1].z = this.temp[1].z;
this.rows[1].w = this.temp[1].w;
this.rows[2].x = this.temp[2].x;
this.rows[2].y = this.temp[2].y;
this.rows[2].z = this.temp[2].z;
this.rows[2].w = this.temp[2].w;
this.rows[3].x = this.temp[3].x;
this.rows[3].y = this.temp[3].y;
this.rows[3].z = this.temp[3].z;
this.rows[3].w = this.temp[3].w;
return this;
};
/**
* Runtime mouse for updating instance objects
* @param graphics GameLib.D3.Graphics
* @param apiMouse GameLib.API.Mouse
* @constructor
*/
GameLib.Mouse = function (graphics, apiMouse) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiMouse)){
apiMouse = {};
}
if (apiMouse instanceof GameLib.Mouse) {
return apiMouse;
}
GameLib.API.Mouse.call(
this,
apiMouse.id,
apiMouse.name,
apiMouse.x,
apiMouse.y,
apiMouse.parentEntity
);
GameLib.Component.call(
this,
GameLib.Component.COMPONENT_MOUSE
);
};
GameLib.Mouse.prototype = Object.create(GameLib.API.Mouse.prototype);
GameLib.Mouse.prototype.constructor = GameLib.Mouse;
/**
* Creates an instance mouse
* @param update
* @returns {*}
*/
GameLib.Mouse.prototype.createInstance = function(update) {
this.instance = true;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* Updates the instance vector, calls updateInstance on the parent object
*/
GameLib.Mouse.prototype.updateInstance = function() {
};
/**
* Converts runtime vector to API Vector
* @returns {GameLib.API.Mouse}
*/
GameLib.Mouse.prototype.toApiObject = function() {
return new GameLib.API.Mouse(
this.id,
this.name,
this.x,
this.y,
this.parentEntity
);
};
/**
* Runtime quaternion for updating instance objects
* @param implementation
* @param parentObject GameLib.D3.*
* @param apiQuaternion GameLib.API.Quaternion
* @param grain Number
* @constructor
*/
GameLib.Quaternion = function (
implementation,
apiQuaternion,
parentObject,
grain
) {
this.implementation = implementation;
if (implementation instanceof GameLib.D3.Graphics) {
this.physics = null;
this.graphics = implementation;
this.graphics.isNotThreeThrow();
} else if (implementation instanceof GameLib.D3.Physics) {
this.graphics = null;
this.physics = implementation;
this.physics.isNotCannonThrow();
} else {
throw new Error('Unhandled implementation : ' + implementation);
}
if (GameLib.Utils.UndefinedOrNull(apiQuaternion)) {
apiQuaternion = {};
}
if (apiQuaternion instanceof GameLib.Quaternion) {
return apiQuaternion;
}
GameLib.API.Quaternion.call(
this,
apiQuaternion.x,
apiQuaternion.y,
apiQuaternion.z,
apiQuaternion.w,
apiQuaternion.axis,
apiQuaternion.angle
);
if (GameLib.Utils.UndefinedOrNull(parentObject)) {
parentObject = null;
}
this.parentObject = parentObject;
this.axis = new GameLib.Vector3(
this.implementation,
this.axis,
this,
this.grain
);
Object.defineProperty(
this,
'angle',
GameLib.Utils.LimitToPI('angle', this.angle)
);
if (GameLib.Utils.UndefinedOrNull(grain)) {
grain = 0.001;
}
this.grain = grain;
this.createInstance();
};
GameLib.Quaternion.prototype = Object.create(GameLib.API.Quaternion.prototype);
GameLib.Quaternion.prototype.constructor = GameLib.Quaternion;
/**
* Creates an instance quaternion
* @returns {*}
*/
GameLib.Quaternion.prototype.createInstance = function() {
if (this.graphics) {
this.instance = new THREE.Quaternion(
this.x,
this.y,
this.z,
this.w
);
}
if (this.physics) {
this.instance = new CANNON.Quaternion(
this.x,
this.y,
this.z,
this.w
);
}
};
/**
* Updates the instance vector, calls updateInstance on the parent object
*/
GameLib.Quaternion.prototype.updateInstance = function(property) {
this.instance.x = this.x;
this.instance.y = this.y;
this.instance.z = this.z;
this.instance.w = this.w;
if (this.parentObject &&
this.parentObject.updateInstance) {
this.parentObject.updateInstance(property);
}
};
/**
* Converts runtime quaternion to API quaternion
* @returns {*}
*/
GameLib.Quaternion.prototype.toApiObject = function() {
return new GameLib.API.Quaternion(
this.x,
this.y,
this.z,
this.w,
this.axis.toApiObject(),
this.angle
);
};
/**
* Checks if quaternion is equal to another quaternion
* @param quaternion
* @returns {boolean}
*/
GameLib.Quaternion.prototype.equals = function(quaternion) {
return (
this.x === quaternion.x &&
this.y === quaternion.y &&
this.z === quaternion.z &&
this.w === quaternion.w &&
this.axis.equals(quaternion.axis) &&
this.angle === quaternion.angle
);
};
GameLib.Quaternion.prototype.setFrom = function(quaternion) {
this.x = quaternion.x;
this.y = quaternion.y;
this.z = quaternion.z;
this.w = quaternion.w;
this.axis.setFrom(quaternion.axis);
this.angle = quaternion.angle;
};
GameLib.Quaternion.prototype.copy = function(quaternion) {
console.log('todo');
};
/**
* System takes care of updating all the entities (based on their component data)
* @param implementation
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System = function(
apiSystem
) {
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.parentEntity
);
this.started = false;
this.paused = false;
var componentType = GameLib.Component.COMPONENT_SYSTEM;
var linkedObjects = {};
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) {
componentType = GameLib.Component.COMPONENT_SYSTEM_ANIMATION;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_CUSTOM) {
componentType = GameLib.Component.COMPONENT_SYSTEM_CUSTOM_CODE;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_GUI) {
componentType = GameLib.Component.COMPONENT_SYSTEM_GUI;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_INPUT) {
componentType = GameLib.Component.COMPONENT_SYSTEM_INPUT;
linkedObjects.mouseControls = [GameLib.D3.Controls.Mouse];
linkedObjects.keyboardControls = [GameLib.D3.Controls.Keyboard];
linkedObjects.touchControls = [GameLib.D3.Controls.Touch];
linkedObjects.editorControls = [GameLib.D3.Controls.Editor];
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_LINKING) {
componentType = GameLib.Component.COMPONENT_SYSTEM_LINKING;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_PHYSICS) {
componentType = GameLib.Component.COMPONENT_SYSTEM_PHYSICS;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_RENDER) {
componentType = GameLib.Component.COMPONENT_SYSTEM_RENDER;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) {
componentType = GameLib.Component.COMPONENT_SYSTEM_STORAGE;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_VISUALIZATION) {
componentType = GameLib.Component.COMPONENT_SYSTEM_VISUALIZATION;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_PARTICLE) {
componentType = GameLib.Component.COMPONENT_SYSTEM_PARTICLE;
}
if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_AUDIO) {
componentType = GameLib.Component.COMPONENT_SYSTEM_AUDIO;
linkedObjects.audioComponents = [GameLib.D3.Audio];
}
GameLib.Component.call(
this,
componentType
);
};
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_PHYSICS = 0x20;
GameLib.System.SYSTEM_TYPE_LINKING = 0x40;
GameLib.System.SYSTEM_TYPE_CUSTOM = 0x80;
GameLib.System.SYSTEM_TYPE_VISUALIZATION = 0x100;
GameLib.System.SYSTEM_TYPE_PARTICLE = 0x200;
GameLib.System.SYSTEM_TYPE_AUDIO = 0x400;
GameLib.System.SYSTEM_TYPE_ALL = 0xFFFF;
GameLib.System.prototype.createInstance = function() {
this.instance = true;
GameLib.Component.prototype.createInstance.call(this);
};
/**
* @callback
* @override
*/
GameLib.System.prototype.start = function() {
this.started = true;
console.log('starting ' + this.name);
};
/**
* @callback
* @override
*/
GameLib.System.prototype.stop = function() {
this.started = false;
console.log('stopping ' + this.name);
};
/**
* 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.parentEntity)
);
};
GameLib.System.prototype.restart = function() {
console.log('restarting system : ' + this.name);
this.stop();
this.start();
};
/**
* System takes care of updating all the entities (based on their component data)
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.Animation = function(
apiSystem
) {
GameLib.System.call(
this,
apiSystem
);
this.animations = {};
this.latest = {};
this.textures = {};
this.textureIds = [];
this.animationMeshAddedSubscription = null;
this.animationMeshRemovedSubscription = null;
this.instanceCreatedSubscription = null;
this.removeComponentSubscription = null;
this.textureAnimatedSubscription = null;
/**
* Sometimes we want to animate texture instances directly, without the overhead of a GameLib.Texture
*/
this.animateTextureInstanceSubscription = null;
};
GameLib.System.Animation.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Animation.prototype.constructor = GameLib.System.Animation;
GameLib.System.Animation.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.beforeRenderSubscription = GameLib.Event.Subscribe(
GameLib.Event.BEFORE_RENDER,
this.beforeRender.bind(this)
);
var animations = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Animation);
animations.map(function(animation){
animation.meshes.map(
function(mesh) {
this.attachAnimation(animation, mesh);
}.bind(this)
)
}.bind(this));
this.animationMeshAddedSubscription = GameLib.Event.Subscribe(
GameLib.Event.ANIMATION_MESH_ADDED,
function(data) {
this.attachAnimation(data.animation, data.mesh);
}.bind(this)
);
this.animationMeshRemovedSubscription = GameLib.Event.Subscribe(
GameLib.Event.ANIMATION_MESH_REMOVED,
function(data) {
this.detachAnimation(data.mesh);
}.bind(this)
);
this.instanceCreatedSubscription = GameLib.Event.Subscribe(
GameLib.Event.INSTANCE_CREATED,
this.instanceCreated.bind(this)
);
this.removeComponentSubscription = GameLib.Event.Subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent.bind(this)
);
this.textureAnimatedSubscription = GameLib.Event.Subscribe(
GameLib.Event.TEXTURE_ANIMATED_CHANGE,
this.textureAnimatedChange.bind(this)
);
this.animateTextureInstanceSubscription = GameLib.Event.Subscribe(
GameLib.Event.ANIMATE_TEXTURE_INSTANCE,
this.animateTextureInstance.bind(this)
)
};
GameLib.System.Animation.prototype.instanceCreated = function(data) {
if (
data.component instanceof GameLib.D3.Texture &&
data.component.animated
) {
if (data.component.repeat.x > 1 || data.component.repeat.x < 0) {
console.warn('cannot animate a texture with repeat.x greater than 1 or less than 0');
data.component.animated = false;
return;
}
if (data.component.repeat.y > 1 || data.component.repeat.y < 0) {
console.warn('cannot animate a texture with repeat.y greater than 1 or less than 0');
data.component.animated = false;
return;
}
this.textures[data.component.id] = data.component;
this.textureIds = Object.keys(this.textures);
}
};
GameLib.System.Animation.prototype.removeComponent = function(data) {
if (
data.component instanceof GameLib.D3.Texture &&
data.component.animated
) {
if (GameLib.Utils.UndefinedOrNull(this.textures[data.component.id])) {
console.warn('tried to remove an animated texture, which should have been in the list but isnt: ' + data.component.name);
} else {
delete this.textures[data.component.id];
this.textureIds = Object.keys(this.textures);
}
}
};
GameLib.System.Animation.prototype.textureAnimatedChange = function(data) {
if (data.texture.animated) {
if (data.texture.repeat.x > 1 || data.texture.repeat.x < 0) {
console.warn('cannot animate a texture with repeat.x greater than 1 or less than 0');
data.texture.animated = false;
return;
}
if (data.texture.repeat.y > 1 || data.texture.repeat.y < 0) {
console.warn('cannot animate a texture with repeat.y greater than 1 or less than 0');
data.texture.animated = false;
return;
}
this.textures[data.texture.id] = data.texture;
this.textureIds = Object.keys(this.textures);
} else {
if (GameLib.Utils.UndefinedOrNull(this.textures[data.texture.id])) {
console.warn('tried to remove an animated texture, which should have been in the list but isnt: ' + data.texture.name);
} else {
delete this.textures[data.texture.id];
this.textureIds = Object.keys(this.textures);
}
}
};
/**
* This adds a texture instance directly on our textures to be animated - to bypass our GameLib component and linking
* system, which adds too much overhead for managing textures
* @param data
*/
GameLib.System.Animation.prototype.animateTextureInstance = function(data) {
if (data.texture.repeat.x > 1 || data.texture.repeat.x < 0) {
console.warn('cannot animate a texture with repeat.x greater than 1 or less than 0');
data.texture.userData.animated = false;
return;
}
if (data.texture.repeat.y > 1 || data.texture.repeat.y < 0) {
console.warn('cannot animate a texture with repeat.y greater than 1 or less than 0');
data.texture.userData.animated = false;
return;
}
data.texture.userData.animated = true;
this.textures[data.texture.id] = data.texture;
this.textureIds = Object.keys(this.textures);
};
GameLib.System.Animation.prototype.beforeRender = function(data) {
if (this.paused) {
return;
}
var delta = data.delta;
for (var property in this.animations) {
if (this.animations.hasOwnProperty(property)) {
var processing = [];
if (this.animations[property].length > 0) {
var rotationDone = false;
var positionDone = false;
var scaleDone = false;
for (var i = 0; i < this.animations[property].length; i++) {
if (this.animations[property][i].type === 'rotation' && !rotationDone) {
rotationDone = true;
processing.push(this.animations[property][i]);
}
if (this.animations[property][i].type === 'position' && !positionDone) {
// if (this.animations[property][i].animation.blocking.position) {
// positionDone = true;
// }
processing.push(this.animations[property][i]);
}
if (this.animations[property][i].type === 'scale' && !scaleDone) {
//scaleDone = true;
processing.push(this.animations[property][i]);
}
if (scaleDone && positionDone && rotationDone) {
break;
}
}
}
processing.map(
function(__property) {
return function(animationObject) {
var done = false;
var increment = 0;
if (animationObject.type === 'rotation') {
increment = animationObject.animation.rotationSpeed * delta;
}
if (animationObject.type === 'position') {
increment = animationObject.animation.translationSpeed * delta;
}
if (animationObject.type === 'scale') {
increment = animationObject.animation.scaleSpeed * delta;
}
if (animationObject.from < animationObject.to) {
animationObject.from += increment;
} else {
animationObject.from -= increment;
}
if (Math.abs(animationObject.from - animationObject.to) < increment) {
animationObject.mesh.instance[animationObject.type][animationObject.axis] = animationObject.to;
done = true;
} else {
animationObject.mesh.instance[animationObject.type][animationObject.axis] = animationObject.from;
}
if (done) {
var index = this.animations[__property].indexOf(animationObject);
this.animations[__property].splice(index, 1);
}
}.bind(this);
}.bind(this)(property)
);
}
}
this.textureIds.map(
function(textureId) {
var texture = this.textures[textureId];
if (texture.reverseAnimation || (texture.userData && texture.userData.reverseAnimation)) {
if (texture.forward === true || (texture.userData && texture.userData.forward === true)) {
texture.offset.x += texture.repeat.x;
if (texture.offset.x >= (1 - texture.repeat.x)) {
if (texture.offset.y >= (1 - texture.repeat.y)) {
texture.offset.x = (1 - texture.repeat.x);
texture.offset.y = (1 - texture.repeat.y);
if (texture.userData) {
texture.userData.forward = false;
} else {
texture.forward = false;
}
} else {
texture.offset.x = 0;
texture.offset.y += texture.repeat.y;
}
}
}
if (texture.forward === false || (texture.userData && texture.userData.forward === false)) {
texture.offset.x -= texture.repeat.x;
if (texture.offset.x <= 0) {
texture.offset.x = 0;
if (texture.offset.y < texture.repeat.y) {
texture.offset.x = texture.repeat.x;
texture.offset.y = 0;
if (texture.userData) {
texture.userData.forward = true;
} else {
texture.forward = true;
}
} else {
texture.offset.x = (1 - texture.repeat.x);
texture.offset.y -= texture.repeat.y;
}
}
}
} else {
texture.offset.x += texture.repeat.x;
if (texture.offset.x >= (1 - texture.repeat.x)) {
if (texture.offset.y >= (1 - texture.repeat.y)) {
texture.offset.x = 0;
texture.offset.y = 0;
} else {
texture.offset.x = 0;
texture.offset.y += texture.repeat.y;
}
}
}
if (!texture.userData) {
texture.updateInstance('offset');
}
}.bind(this)
)
};
GameLib.System.Animation.prototype.detachAnimation = function(mesh) {
var detached = false;
if (mesh.backupQuaternionAngleDescriptor) {
Object.defineProperty(
mesh.quaternion,
'angle',
mesh.backupQuaternionAngleDescriptor
);
delete mesh.backupQuaternionAngleDescriptor;
detached = true;
}
if (mesh.backupQuaternionAxisXDescriptor) {
Object.defineProperty(
mesh.quaternion.axis,
'x',
mesh.backupQuaternionAxisXDescriptor
);
delete mesh.backupQuaternionAxisXDescriptor;
detached = true;
}
if (mesh.backupQuaternionAxisYDescriptor) {
Object.defineProperty(
mesh.quaternion.axis,
'y',
mesh.backupQuaternionAxisYDescriptor
);
delete mesh.backupQuaternionAxisYDescriptor;
detached = true;
}
if (mesh.backupQuaternionAxisZDescriptor) {
Object.defineProperty(
mesh.quaternion.axis,
'z',
mesh.backupQuaternionAxisZDescriptor
);
delete mesh.backupQuaternionAxisXDescriptor;
detached = true;
}
if (mesh.backupRotationXDescriptor) {
Object.defineProperty(
mesh.rotation,
'x',
mesh.backupRotationXDescriptor
);
delete mesh.backupRotationXDescriptor;
detached = true;
}
if (mesh.backupRotationYDescriptor) {
Object.defineProperty(
mesh.rotation,
'y',
mesh.backupRotationYDescriptor
);
delete mesh.backupRotationYDescriptor;
detached = true;
}
if (mesh.backupRotationZDescriptor) {
Object.defineProperty(
mesh.rotation,
'z',
mesh.backupRotationZDescriptor
);
delete mesh.backupRotationZDescriptor;
detached = true;
}
if (mesh.backupPositionXDescriptor) {
Object.defineProperty(
mesh.position,
'x',
mesh.backupPositionXDescriptor
);
delete mesh.backupPositionXDescriptor;
detached = true;
}
if (mesh.backupPositionYDescriptor) {
Object.defineProperty(
mesh.position,
'y',
mesh.backupPositionYDescriptor
);
delete mesh.backupPositionYDescriptor;
detached = true;
}
if (mesh.backupPositionZDescriptor) {
Object.defineProperty(
mesh.position,
'z',
mesh.backupPositionZDescriptor
);
delete mesh.backupPositionZDescriptor;
detached = true;
}
if (mesh.backupScaleXDescriptor) {
Object.defineProperty(
mesh.scale,
'x',
mesh.backupScaleXDescriptor
);
delete mesh.backupScaleXDescriptor;
detached = true;
}
if (mesh.backupScaleYDescriptor) {
Object.defineProperty(
mesh.scale,
'y',
mesh.backupScaleYDescriptor
);
delete mesh.backupScaleYDescriptor;
detached = true;
}
if (mesh.backupScaleZDescriptor) {
Object.defineProperty(
mesh.scale,
'z',
mesh.backupScaleZDescriptor
);
delete mesh.backupScaleZDescriptor;
detached = true;
}
if (this.latest[mesh.id]) {
mesh.rotation.x = this.latest[mesh.id].rotation.x;
mesh.rotation.y = this.latest[mesh.id].rotation.y;
mesh.rotation.z = this.latest[mesh.id].rotation.z;
mesh.position.x = this.latest[mesh.id].position.x;
mesh.position.y = this.latest[mesh.id].position.y;
mesh.position.z = this.latest[mesh.id].position.z;
mesh.scale.x = this.latest[mesh.id].scale.x;
mesh.scale.y = this.latest[mesh.id].scale.y;
mesh.scale.z = this.latest[mesh.id].scale.z;
mesh.quaternion.axis.x = this.latest[mesh.id].quaternion.axis.x;
mesh.quaternion.axis.y = this.latest[mesh.id].quaternion.axis.y;
mesh.quaternion.axis.z = this.latest[mesh.id].quaternion.axis.z;
mesh.quaternion.angle = this.latest[mesh.id].quaternion.angle;
delete this.latest[mesh.id];
detached = true;
}
if (this.animations[mesh.id]) {
delete this.animations[mesh.id];
detached = true;
}
if (detached) {
mesh.updateInstance();
}
};
GameLib.System.Animation.prototype.attachAnimation = function(animation, mesh) {
/**
* Initialize the property with the original mesh z value
*/
this.latest[mesh.id] = {
rotation : {
x : mesh.rotation.x,
y : mesh.rotation.y,
z : mesh.rotation.z
},
position : {
x : mesh.position.x,
y : mesh.position.y,
z : mesh.position.z
},
scale : {
x : mesh.scale.x,
y : mesh.scale.y,
z : mesh.scale.z
},
quaternion : {
axis : {
x : mesh.quaternion.axis.x,
y : mesh.quaternion.axis.y,
z : mesh.quaternion.axis.z
},
angle : mesh.quaternion.angle
}
};
this.animations[mesh.id] = [];
if (mesh.backupRotationXDescriptor) {
throw new Error('already a backed up x descriptor');
}
mesh.backupQuaternionAngleDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion, 'angle');
mesh.backupQuaternionAxisXDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion.axis, 'x');
mesh.backupQuaternionAxisYDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion.axis, 'y');
mesh.backupQuaternionAxisZDescriptor = Object.getOwnPropertyDescriptor(mesh.quaternion.axis, 'z');
mesh.backupRotationXDescriptor = Object.getOwnPropertyDescriptor(mesh.rotation, 'x');
mesh.backupRotationYDescriptor = Object.getOwnPropertyDescriptor(mesh.rotation, 'y');
mesh.backupRotationZDescriptor = Object.getOwnPropertyDescriptor(mesh.rotation, 'z');
mesh.backupPositionXDescriptor = Object.getOwnPropertyDescriptor(mesh.position, 'x');
mesh.backupPositionYDescriptor = Object.getOwnPropertyDescriptor(mesh.position, 'y');
mesh.backupPositionZDescriptor = Object.getOwnPropertyDescriptor(mesh.position, 'z');
mesh.backupScaleXDescriptor = Object.getOwnPropertyDescriptor(mesh.scale, 'x');
mesh.backupScaleYDescriptor = Object.getOwnPropertyDescriptor(mesh.scale, 'y');
mesh.backupScaleZDescriptor = Object.getOwnPropertyDescriptor(mesh.scale, 'z');
Object.defineProperty(
mesh.quaternion,
'angle',
{
'get': this.getProperty(mesh, 'angle', 'quaternion'),
'set': this.setProperty(mesh, animation, 'angle', 'quaternion'),
'configurable': true
}
);
Object.defineProperty(
mesh.quaternion.axis,
'x',
{
'get': this.getSubProperty(mesh, 'x', 'quaternion', 'axis'),
'set': this.setSubProperty(mesh, animation, 'x', 'quaternion', 'axis'),
'configurable': true
}
);
Object.defineProperty(
mesh.quaternion.axis,
'y',
{
'get': this.getSubProperty(mesh, 'y', 'quaternion', 'axis'),
'set': this.setSubProperty(mesh, animation, 'y', 'quaternion', 'axis'),
'configurable': true
}
);
Object.defineProperty(
mesh.quaternion.axis,
'z',
{
'get': this.getSubProperty(mesh, 'z', 'quaternion', 'axis'),
'set': this.setSubProperty(mesh, animation, 'z', 'quaternion', 'axis'),
'configurable': true
}
);
Object.defineProperty(
mesh.rotation,
'x',
{
'get': this.getProperty(mesh, 'x', 'rotation'),
'set': this.setProperty(mesh, animation, 'x', 'rotation'),
'configurable': true
}
);
Object.defineProperty(
mesh.rotation,
'y',
{
'get': this.getProperty(mesh, 'y', 'rotation'),
'set': this.setProperty(mesh, animation, 'y', 'rotation'),
'configurable': true
}
);
Object.defineProperty(
mesh.rotation,
'z',
{
'get': this.getProperty(mesh, 'z', 'rotation'),
'set': this.setProperty(mesh, animation, 'z', 'rotation'),
'configurable': true
}
);
Object.defineProperty(
mesh.scale,
'x',
{
'get': this.getProperty(mesh, 'x', 'scale'),
'set': this.setProperty(mesh, animation, 'x', 'scale'),
'configurable': true
}
);
Object.defineProperty(
mesh.scale,
'y',
{
'get': this.getProperty(mesh, 'y', 'scale'),
'set': this.setProperty(mesh, animation, 'y', 'scale'),
'configurable': true
}
);
Object.defineProperty(
mesh.scale,
'z',
{
'get': this.getProperty(mesh, 'z', 'scale'),
'set': this.setProperty(mesh, animation, 'z', 'scale'),
'configurable': true
}
);
Object.defineProperty(
mesh.position,
'x',
{
'get': this.getProperty(mesh, 'x', 'position'),
'set': this.setProperty(mesh, animation, 'x', 'position'),
'configurable': true
}
);
Object.defineProperty(
mesh.position,
'y',
{
'get': this.getProperty(mesh, 'y', 'position'),
'set': this.setProperty(mesh, animation, 'y', 'position'),
'configurable': true
}
);
Object.defineProperty(
mesh.position,
'z',
{
'get': this.getProperty(mesh, 'z', 'position'),
'set': this.setProperty(mesh, animation, 'z', 'position'),
'configurable': true
}
);
};
// GameLib.System.Animation.prototype.getQuaternionAngle = function(mesh, animation) {
//
// return function() {
// return;
// /**
// * TODO: fix this shit..
// * Back up the current property descriptor
// */
// mesh.animationObject = {
// backupAngleDescriptor: Object.getOwnPropertyDescriptor(mesh.quaternion, 'angle'),
// targetAngle: mesh.quaternion.angle,
// angleIncrement: true,
// intermediateAngle: mesh.quaternion.angle,
// subscription: null,
// inProcess: false,
// blocking: animation.blocking//,
// // callbacks : [],
// // storedValues : []
// };
//
// var getIntermediateAngle = function () {
// return mesh.animationObject.intermediateAngle;
// };
//
// var getTargetAngle = function () {
//
// // if (mesh.animationObject.storedValues.length > 0) {
// // return mesh.animationObject.storedValues[mesh.animationObject.storedValues.length - 1];
// // }
//
// return mesh.animationObject.targetAngle;
// };
//
// var animateRotation = function (value) {
//
// mesh.animationObject.intermediateAngle += value;
//
// var done = false;
//
// if (mesh.animationObject.angleIncrement) {
// /**
// * We are rotating upwards
// */
// if (mesh.animationObject.intermediateAngle >= mesh.animationObject.targetAngle) {
// /**
// * We need to stop
// */
// done = true;
// }
// } else {
// /**
// * We are rotating downwards
// */
// if (mesh.animationObject.intermediateAngle <= mesh.animationObject.targetAngle) {
// /**
// * We need to stop
// */
// done = true;
// }
// }
//
// if (done) {
//
// /**
// * We clamp to our target angle
// */
// mesh.animationObject.intermediateAngle = mesh.animationObject.targetAngle;
//
// /**
// * We limit our intermediate angle between values of -pi and pi
// */
// while (mesh.animationObject.intermediateAngle > Math.PI) {
// mesh.animationObject.intermediateAngle -= (Math.PI * 2);
// }
//
// while (mesh.animationObject.intermediateAngle < -(Math.PI)) {
// mesh.animationObject.intermediateAngle += (Math.PI * 2);
// }
//
// /**
// * We apply our new intermediate angle to our target
// */
// mesh.animationObject.targetAngle = mesh.animationObject.intermediateAngle;
// }
//
// /**
// * Apply the actual rotation to the mesh
// */
// mesh.updateInstanceRotationFromAxisAngle(mesh.quaternion.axis, mesh.animationObject.intermediateAngle);
//
// /**
// * Check again if we are done, we need to do some additional work -
// */
// if (done) {
//
// if (!mesh.animationObject.subscription) {
// var message = 'mesh animation object subscription went missing for ';
// message += mesh.name + ': ';
// message += animation.name;
// console.warn(message);
// throw new Error(message);
// }
//
// /**
// * Stop subscribing to before render events
// */
// mesh.animationObject.subscription.remove();
//
// /**
// * @type {null}
// */
// mesh.animationObject.subscription = null;
//
// /**
// * For some meshes, when we are done with the animation, we want to apply
// * the current state of the mesh to the object data itself (i.e. update
// * its vertices etc)
// */
// if (animation.applyToMeshWhenDone) {
// /**
// * Now we say that our intermediate angle is zero, because we will apply our rotation
// * and this will prevent us from re-registering a new 'animationRender' event
// */
// mesh.animationObject.targetAngle = 0;
// mesh.animationObject.intermediateAngle = 0;
//
// /**
// * Apply our position, rotation and scale to the mesh
// */
// mesh.applyPositionRotationScale();
// }
//
// /**
// * Tell our animation component that it is no longer in process...
// * @type {boolean}
// */
// mesh.animationObject.inProcess = false;
//
// // if (mesh.animationObject.callbacks.length > 0) {
// // var callback = mesh.animationObject.callbacks[0];
// // mesh.animationObject.callbacks.splice(0,1);
// // callback();
// // }
//
// // mesh.animationObject.storedValues = [];
// }
// };
// }
// };
//
// GameLib.System.Animation.prototype.setQuaternionAngle = function(mesh, animation) {
//
// return function(value) {
// return;
// /**
// * TODO: update this shit
// */
// /**
// * Check if we have work to do
// */
// if (mesh.animationObject.intermediateAngle === value) {
//
// mesh.animationObject.inProcess = false;
//
// /**
// * Nothing to do
// */
// return;
// }
//
// /**
// * Check if we have another animation in process
// */
// if (mesh.animationObject.inProcess && mesh.animationObject.blocking) {
//
// console.log('another animation is already in process');
//
// // setTargetAngle(value);
//
// // GameLib.Utils.PushUnique(mesh.animationObject.storedValues, value);
// //
// // mesh.animationObject.callbacks.push(
// // function(__value) {
// // return function(){
// // mesh.quaternion.angle = __value;
// // }
// // }(value)
// // );
//
// /**
// * Respond that our angle is actually our target angle (it will be that soon)
// */
// return;
// }
//
// /**
// * We indicate that we now have an animation in process
// * @type {boolean}
// */
// mesh.animationObject.inProcess = true;
//
// /**
// * Ok - all good - lets start the animation
// */
// if (mesh.animationObject.intermediateAngle > value) {
// /**
// * We will rotate towards by decrementing
// */
// mesh.animationObject.angleIncrement = false;
// } else {
// /**
// * We will rotate towards by incrementing
// */
// mesh.animationObject.angleIncrement = true;
// }
//
// /**
// * We say what our target angle is - when we reach our target angle, we want
// * to stop our animation
// */
// mesh.animationObject.targetAngle = value;
//
// /**
// * Now we subscribe to 'before render' events, and slowly increment the value
// * @type {{fn, remove}}
// */
// mesh.animationObject.subscription = GameLib.Event.Subscribe(
// GameLib.Event.BEFORE_RENDER,
// function(data) {
//
// var increment = Math.abs(animation.rotationSpeed);
//
// if (!mesh.animationObject.angleIncrement) {
// increment *= -1;
// }
//
// animateRotation(data.delta * increment);
// }
// );
// }
// };
//
// GameLib.System.Animation.prototype.getQuaternionAxisX = function(mesh, animation) {
// return function() {
// return this.latest[mesh.id].quaternion.axis.x;
// }.bind(this);
// };
//
// GameLib.System.Animation.prototype.setQuaternionAxisX = function(mesh, animation) {
// return function(value) {
// this.latest[mesh.id].quaternion.axis.x = value;
// }.bind(this);
// };
//
// GameLib.System.Animation.prototype.getQuaternionAxisY = function(mesh, animation) {
// return function() {
// return this.latest[mesh.id].quaternion.axis.y;
// }.bind(this);
// };
//
// GameLib.System.Animation.prototype.setQuaternionAxisY = function(mesh, animation) {
// return function(value) {
// this.latest[mesh.id].quaternion.axis.y = value;
// }.bind(this);
// };
//
// GameLib.System.Animation.prototype.getQuaternionAxisZ = function(mesh, animation) {
// return function() {
// return this.latest[mesh.id].quaternion.axis.z;
// }.bind(this);
// };
//
// GameLib.System.Animation.prototype.setQuaternionAxisZ = function(mesh, animation) {
// return function(value) {
// this.latest[mesh.id].quaternion.axis.z = value;
// }.bind(this);
// };
GameLib.System.Animation.prototype.getSubProperty = function(mesh, axis, property, subProperty) {
return function() {
return this.latest[mesh.id][property][subProperty][axis];
}.bind(this);
};
GameLib.System.Animation.prototype.setSubProperty = function(mesh, animation, axis, property, subProperty) {
return function(value) {
var from = Number(this.latest[mesh.id][property][subProperty][axis]);
this.latest[mesh.id][property][subProperty][axis] = value;
if (property === 'position') {
/**
* Look for other position animations
* TODO:check when not super exausted
*/
// var positionAnimationObject = this.animations[mesh.id].reduce(
// function(result, animationObject) {
//
// if (animationObject.type === 'position') {
// result = animationObject;
// }
//
// return result;
// },
// null
// );
/**
* We found another position animation - just update the 'to' property
*/
// if (positionAnimationObject) {
// positionAnimationObject.to = value;
// return;
// }
}
this.animations[mesh.id].push(
{
type : property,
axis : axis,
from : from,
to : value,
animation : animation,
mesh : mesh
}
);
}.bind(this)
};
GameLib.System.Animation.prototype.getProperty = function(mesh, axis, property) {
return function() {
return this.latest[mesh.id][property][axis];
}.bind(this);
};
GameLib.System.Animation.prototype.setProperty = function(mesh, animation, axis, property) {
return function(value) {
var from = Number(this.latest[mesh.id][property][axis]);
this.latest[mesh.id][property][axis] = value;
if (property === 'position') {
/**
* Look for other position animations
* TODO:check when not super exausted
*/
// var positionAnimationObject = this.animations[mesh.id].reduce(
// function(result, animationObject) {
//
// if (animationObject.type === 'position') {
// result = animationObject;
// }
//
// return result;
// },
// null
// );
/**
* We found another position animation - just update the 'to' property
*/
// if (positionAnimationObject) {
// positionAnimationObject.to = value;
// return;
// }
}
this.animations[mesh.id].push(
{
type : property,
axis : axis,
from : from,
to : value,
animation : animation,
mesh : mesh
}
);
}.bind(this)
};
/**
* Stop Animation System
*/
GameLib.System.Animation.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.beforeRenderSubscription.remove();
this.animationMeshAddedSubscription.remove();
this.animationMeshRemovedSubscription.remove();
this.animations = {};
var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh);
meshes.map(
function(mesh) {
for (var property in this.latest) {
if (
this.latest.hasOwnProperty(property) &&
property === mesh.id
) {
this.detachAnimation(mesh);
}
}
}.bind(this)
);
this.instanceCreatedSubscription.remove();
this.removeComponentSubscription.remove();
this.textureAnimatedSubscription.remove();
this.animateTextureInstanceSubscription.remove();
};
/**
* System takes care of updating all the entities (based on their component data)
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.Audio = function(
apiSystem
) {
GameLib.System.call(
this,
apiSystem
);
this.instanceCreatedSubscription = null;
this.removeComponentSubscription = null;
this.playAudioSubscription = null;
this.pauseAllAudioSubscription = null;
this.muteAudioSubscription = null;
this.continueAllAudioSubscription = null;
this.stopAudioSubscription = null;
this.stopAllAudioSubscription = null;
this.mute = false;
this.paused = [];
this.audioComponents = [];
this.toPlay = [];
};
GameLib.System.Audio.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Audio.prototype.constructor = GameLib.System.Audio;
/**
* Start this system (add all event listeners)
*/
GameLib.System.Audio.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.instanceCreatedSubscription = GameLib.Event.Subscribe(
GameLib.Event.INSTANCE_CREATED,
this.instanceCreated.bind(this)
);
this.removeComponentSubscription = GameLib.Event.Subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent.bind(this)
);
this.playAudioSubscription = GameLib.Event.Subscribe(
GameLib.Event.PLAY_AUDIO,
this.playAudio.bind(this)
);
this.pauseAllAudioSubscription = GameLib.Event.Subscribe(
GameLib.Event.PAUSE_ALL_AUDIO,
this.pauseAllAudio.bind(this)
);
this.muteAudioSubscription = GameLib.Event.Subscribe(
GameLib.Event.MUTE_AUDIO,
this.muteAudio.bind(this)
);
this.continueAllAudioSubscription = GameLib.Event.Subscribe(
GameLib.Event.CONTINUE_ALL_AUDIO,
this.continueAllAudio.bind(this)
);
this.stopAudioSubscription = GameLib.Event.Subscribe(
GameLib.Event.STOP_AUDIO,
this.stopAudio.bind(this)
);
this.stopAllAudioSubscription = GameLib.Event.Subscribe(
GameLib.Event.STOP_ALL_AUDIO,
this.stopAllAudio.bind(this)
);
};
/**
* From now on we want to track everything about a component, only from the systems that are active
* @param data
*/
GameLib.System.Audio.prototype.instanceCreated = function(data) {
if (data.component instanceof GameLib.D3.Audio) {
GameLib.Utils.PushUnique(this.audioComponents, data.component);
data.component.instance.onEnded = function() {
this.isPlaying = false;
GameLib.Event.Emit(
GameLib.Event.AUDIO_ENDED,
{
audio : data.component
}
);
};
var index = this.toPlay.indexOf(data.component.name);
if (index !== -1) {
GameLib.Event.Emit(
GameLib.Event.PLAY_AUDIO,
{
name : data.component.name
}
);
this.toPlay.splice(index, 1);
}
}
};
/**
* Removes a particle engine from this system
* @param data
*/
GameLib.System.Audio.prototype.playAudio = function(data) {
var found = false;
this.audioComponents.map(
function(audio) {
if (audio.name === data.name) {
found = true;
if (!audio.instance) {
console.log('audio not ready yet');
}
if (audio.overplay) {
if (audio.instance.isPlaying) {
audio.instance.stop();
}
audio.instance.offset = 0;
audio.instance.play();
} else if (!audio.instance.isPlaying) {
audio.instance.play();
}
}
}
);
if (!found) {
/**
* This audio still has to load
*/
console.log('delaying audio play until loaded for: ' + data.name);
this.toPlay.push(data.name);
}
};
GameLib.System.Audio.prototype.pauseAllAudio = function(data) {
this.paused = [];
this.audioComponents.map(
function(audio) {
if (audio.instance.isPlaying) {
this.paused.push(audio);
// audio.currentTime = audio.instance.context.currentTime;
audio.paused = true;
audio.updateInstance('paused');
}
}.bind(this)
)
};
GameLib.System.Audio.prototype.continueAllAudio = function(data) {
this.paused.map(
function(audio) {
// audio.instance.context.currentTime = audio.currentTime;
audio.paused = false;
audio.updateInstance('paused');
}
);
this.paused = [];
};
GameLib.System.Audio.prototype.stopAllAudio = function(data) {
this.audioComponents.map(
function(audio) {
if (audio.instance.isPlaying) {
audio.instance.stop();
}
}
)
};
GameLib.System.Audio.prototype.stopAudio = function(data) {
this.audioComponents.map(
function(audio) {
if (audio.name === data.name) {
if (audio.instance.isPlaying) {
audio.instance.stop();
}
}
}
)
};
GameLib.System.Audio.prototype.removeComponent = function(data) {
};
GameLib.System.Audio.prototype.muteAudio = function() {
this.mute = !this.mute;
if (this.mute) {
this.audioVolumes = this.audioComponents.reduce(
function(result, audio) {
result.push(
{
audio : audio,
volume : audio.volume
}
);
audio.volume = 0;
audio.updateInstance('volume');
return result;
},
[]
);
GameLib.Event.Emit(GameLib.Event.AUDIO_MUTED, {audioSystem:this});
} else {
this.audioVolumes.map(
function(audioVolume) {
audioVolume.audio.volume = audioVolume.volume;
audioVolume.audio.updateInstance('volume');
}
);
GameLib.Event.Emit(GameLib.Event.AUDIO_UNMUTED, {audioSystem:this});
}
};
/**
* Stop this system (remove all event listeners)
*/
GameLib.System.Audio.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.instanceCreatedSubscription.remove();
this.removeComponentSubscription.remove();
this.playAudioSubscription.remove();
this.pauseAllAudioSubscription.remove();
this.muteAudioSubscription.remove();
this.continueAllAudioSubscription.remove();
this.stopAudioSubscription.remove();
this.stopAllAudioSubscription.remove();
};
/**
* System takes care of updating all the entities (based on their component data)
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.CustomCode = function(
apiSystem
) {
GameLib.System.call(
this,
apiSystem
);
this.instanceCreatedSubscription = null;
this.removeComponentSubscription = null;
this.compileSuccessSubscription = null;
this.compileFailedSubscription = null;
this.subscriptions = {};
};
GameLib.System.CustomCode.prototype = Object.create(GameLib.System.prototype);
GameLib.System.CustomCode.prototype.constructor = GameLib.System.CustomCode;
/**
* Start the rendering system
*/
GameLib.System.CustomCode.prototype.start = function() {
GameLib.System.prototype.start.call(this);
GameLib.EntityManager.Instance.queryComponents(GameLib.D3.CustomCode).map(
function(component) {
this.subscriptions[component.id] = GameLib.Event.Subscribe(
component.eventId,
component.instance
);
}.bind(this)
);
this.instanceCreatedSubscription = GameLib.Event.Subscribe(
GameLib.Event.INSTANCE_CREATED,
this.instanceCreated.bind(this)
);
this.removeComponentSubscription = GameLib.Event.Subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent.bind(this)
);
this.compileSuccessSubscription = GameLib.Event.Subscribe(
GameLib.Event.COMPILE_SUCCESS,
this.compileSuccess.bind(this)
);
this.compileFailedSubscription = GameLib.Event.Subscribe(
GameLib.Event.COMPILE_FAILED,
this.compileFailed.bind(this)
);
};
GameLib.System.CustomCode.prototype.instanceCreated = function(data) {
if (data.component instanceof GameLib.D3.CustomCode) {
if (this.subscriptions[data.component.id]) {
console.warn('a component already existed');
this.subscriptions[data.component.id].remove();
}
this.subscriptions[data.component.id] = GameLib.Event.Subscribe(
data.component.eventId,
data.component.instance
);
}
};
GameLib.System.CustomCode.prototype.removeComponent = function(data) {
if (data.component instanceof GameLib.D3.CustomCode) {
if (this.subscriptions[data.component.id]) {
this.subscriptions[data.component.id].remove();
delete this.subscriptions[data.component.id];
}
}
};
GameLib.System.CustomCode.prototype.compileSuccess = function(data) {
if (this.subscriptions[data.component.id]) {
this.subscriptions[data.component.id].remove();
}
this.subscriptions[data.component.id] = GameLib.Event.Subscribe(
data.component.eventId,
data.component.instance
);
};
GameLib.System.CustomCode.prototype.compileFailed = function(data) {
if (this.subscriptions[data.component.id]) {
this.subscriptions[data.component.id].remove();
delete this.subscriptions[data.component.id];
}
};
/**
* Stop the rendering system
*/
GameLib.System.CustomCode.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
if (this.instanceCreatedSubscription) {
this.instanceCreatedSubscription.remove();
this.instanceCreatedSubscription = null;
}
if (this.removeComponentSubscription) {
this.removeComponentSubscription.remove();
this.removeComponentSubscription = null;
}
if (this.compileSuccessSubscription) {
this.compileSuccessSubscription.remove();
this.compileSuccessSubscription = null;
}
if (this.compileFailedSubscription) {
this.compileFailedSubscription.remove();
this.compileFailedSubscription = null;
}
Object.keys(this.subscriptions).map(
function(componentId) {
if (this.subscriptions[componentId]) {
this.subscriptions[componentId].remove();
delete this.subscriptions[componentId];
}
}.bind(this)
);
};
/**
* 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.components = [];
/**
* When we want to show a specific set of components - we backup the current components and then restore them
* later when we are done.
* @type {null}
*/
this.backupComponents = [];
this.exclusiveMode = false;
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() {
GameLib.System.prototype.start.call(this);
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.listen = function(controller) {
const init = this.__listening.length === 0;
this.__listening.push(controller);
delete this.closed;
Object.defineProperty(this, 'closed', {
get: function() {
return this.params.closed;
},
set: function(v) {
// console.log('override here too');
this.params.closed = v;
if (this.params.closed) {
this.dom.addClass(this.__ul, 'closed');
cancelAnimationFrame(this.animationId);
} else {
this.dom.removeClass(this.__ul, 'closed');
this.updateDisplaysCallback = function() {
/**
* We store the animationFrameId so we can remove this callback later
*/
this.animationId = requestAnimationFrame(this.updateDisplaysCallback.bind(this));
this.__listening.map(function(controller){
controller.updateDisplay();
});
}.bind(this);
this.animationId = requestAnimationFrame(this.updateDisplaysCallback);
}
// For browsers that aren't going to respect the CSS transition,
// Lets just check our height against the window height right off
// the bat.
this.onResize();
if (this.__closeButton) {
this.__closeButton.innerHTML = v ? 'Open Controls' : 'Close Controls';
}
},
configurable: true
});
};
dat.GUI.prototype.removeAllFolders = function() {
for (var property in this.__folders) {
if (this.__folders.hasOwnProperty(property)){
var folder = this.__folders[property];
/**
* Theres a big 'TODO' in the controller remove() function to actually remove the listener
* That's what we are going to do now.. - because it really fucks with the framerate eventually
*/
cancelAnimationFrame(folder.animationId);
folder.__controllers.map(
function(controller) {
controller.remove();
}
);
folder.__controllers = [];
folder.__listening = [];
/**
* Call UpdateDisplays with
*/
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.REMOVE_MESH,
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
);
this.componentRemovedSubscription = this.subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent
)
};
GameLib.System.GUI.prototype.onChange = function(property, subProperty, affected) {
return function(value) {
affected.map(function(component){
component[property][subProperty] = value;
if (component instanceof GameLib.D3.Mesh && property === 'rotation') {
component.useQuaternion = false;
}
if (component instanceof GameLib.D3.Mesh && property === 'quaternion') {
component.useQuaternion = true;
}
if (typeof component[property].updateInstance === 'function') {
component[property].updateInstance(property);
} else if (typeof component[property][subProperty].updateInstance === 'function') {
component[property][subProperty].updateInstance(subProperty);
} else {
component.updateInstance(property);
}
});
}
};
GameLib.System.GUI.prototype.controller = function(folder, object, property, subProperty, step, listen, affected, min, max) {
if (GameLib.Utils.UndefinedOrNull(min)) {
min = -1000;
}
if (GameLib.Utils.UndefinedOrNull(max)) {
max = 1000;
}
if (
// property === 'chassisConnectionPointLocal' ||
property === 'axleLocal' ||
property === 'directionLocal'
) {
min = -1;
max = 1;
step = 1;
}
if (
// property === 'chassisConnectionPointLocal' ||
property === 'offset' ||
property === 'repeat'
) {
min = -1000;
max = 1000;
step = 0.00001;
}
var handle = folder.add(
object[property],
subProperty,
min,
max,
step
).name(property + '.' + subProperty);
handle.onChange(this.onChange(property, subProperty, affected));
if (listen) {
handle.listen();
}
return handle;
};
GameLib.System.GUI.prototype.buildQuaternionControl = function(folder, componentTemplate, property) {
var step = 0.1;
var object = componentTemplate.template;
var listen = false;
if (componentTemplate.affected.length === 1) {
/**
* If the template only affects a single object - put the handle on this so we can listen for changes
*/
object = componentTemplate.affected[0];
listen = true;
}
var affected = componentTemplate.affected;
this.controller(folder, object, property, 'x', step, listen, affected);
this.controller(folder, object, property, 'y', step, listen, affected);
this.controller(folder, object, property, 'z', step, listen, affected);
this.controller(folder, object, property, 'w', step, listen, affected);
this.controller(folder, object, property, 'angle', 0.001, listen, affected, -Math.PI, Math.PI);
folder.add(
object[property]['axis'],
'x',
-1,
1,
0.01
).name('quaternion.axis.x').onChange(
function(value) {
affected.map(function(component){
component.useQuaternion = true;
component[property]['axis'].x = Number(value);
component.updateInstance('x');
})
}
);
folder.add(
object[property]['axis'],
'y',
-1,
1,
0.01
).name('quaternion.axis.y').onChange(
function(value) {
affected.map(function(component){
component.useQuaternion = true;
component[property]['axis'].y = Number(value);
component.updateInstance('y');
})
}
);
folder.add(
object[property]['axis'],
'z',
-1,
1,
0.01
).name('quaternion.axis.z').onChange(
function(value) {
affected.map(function(component){
component.useQuaternion = true;
component[property]['axis'].z = Number(value);
component.updateInstance('z');
})
}
);
};
GameLib.System.GUI.prototype.buildVectorControl = function(folder, componentTemplate, property) {
var step = 0.01;
var object = componentTemplate.template;
var listen = false;
if (componentTemplate.affected.length === 1) {
/**
* If the template only affects a single object - put the handle on this so we can listen for changes
*/
object = componentTemplate.affected[0];
listen = true;
}
var affected = componentTemplate.affected;
var controllers = [];
if (GameLib.Utils.isVector4(object[property])) {
controllers.push(this.controller(folder, object, property, 'w', step, listen, affected));
}
controllers.push(this.controller(folder, object, property, 'x', step, listen, affected));
controllers.push(this.controller(folder, object, property, 'y', step, listen, affected));
if (
GameLib.Utils.isVector3(object[property]) ||
GameLib.Utils.isVector4(object[property])
) {
controllers.push(this.controller(folder, object, property, 'z', step, listen, affected));
}
};
/**
* Builds an Entity Selection control
* @param folder
* @param componentTemplate
*/
GameLib.System.GUI.prototype.buildParentSelectionControl = function(folder, componentTemplate, property) {
var constructor = null;
if (property === 'parentEntity') {
constructor = GameLib.Entity;
}
if (property === 'parentMesh') {
constructor = GameLib.D3.Mesh;
}
if (property === 'parentWorld') {
constructor = GameLib.D3.PhysicsWorld;
}
if (property === 'parentScene') {
constructor = GameLib.D3.Scene;
}
var options = GameLib.EntityManager.Instance.queryComponents(constructor).reduce(
function(result, object) {
result[object.name] = object;
return result;
},
{
'none' : null
}
);
var object = componentTemplate.template;
var affected = componentTemplate.affected;
folder.add(object, property, options).listen().onChange(
function(value) {
var newComponent = null;
if (value !== 'null') {
newComponent = GameLib.EntityManager.Instance.findComponentById(value);
}
affected.map(
function(component) {
component[property] = newComponent;
if (property === 'parentEntity') {
GameLib.Event.Emit(
GameLib.Event.PARENT_ENTITY_CHANGE,
{
originalEntity : this.initialValue,
newEntity : newComponent,
object : component
}
);
}
if (property === 'parentWorld') {
GameLib.Event.Emit(
GameLib.Event.PARENT_WORLD_CHANGE,
{
originalWorld : this.initialValue,
newWorld : newComponent,
object : component
}
)
}
if (property === 'parentScene') {
GameLib.Event.Emit(
GameLib.Event.PARENT_SCENE_CHANGE,
{
originalScene: this.initialValue,
newScene: newComponent,
object: component
}
);
}
}.bind(this)
);
if (property === 'parentEntity') {
GameLib.Event.Emit(
GameLib.Event.BUILD_GUI,
null
);
}
this.initialValue = newComponent;
}
);
};
GameLib.System.GUI.prototype.buildArrayManagerControl = function(
folder,
componentTemplate,
property
) {
var constructors = componentTemplate.template.linkedObjects[property];
if (constructors instanceof Array) {
/**
* All good
*/
} else {
/**
* There is a data mismatch
*/
console.error('data mismatch - something not an array');
return;
}
var object = componentTemplate.template;
var array = object[property];
var addArrayItem = function(item, index){
var name = 'invalid item';
if (item && item.name) {
name = item.name;
}
var controller = folder.add(
{
'remove' : function() {
componentTemplate.affected.map(function(component){
component[property].splice(index, 1);
folder.remove(controller);
});
}
},
'remove'
).name('remove ' + property + '[' + index + '] - ' + name);
folder.updateDisplay();
};
array.map(addArrayItem);
var idObject = {};
var selectionObject = GameLib.EntityManager.Instance.queryComponents(constructors).reduce(
function(result, component) {
result[component.name] = component;
idObject[component.id] = component;
return result;
},
{
'none' : null
}
);
var activeSelection = {
component: null,
add: function () {
componentTemplate.affected.map(function (component) {
if (component[property].indexOf(activeSelection.component) === -1) {
component[property].push(activeSelection.component);
GameLib.Event.Emit(
GameLib.Event.ARRAY_ITEM_ADDED,
{
component : component,
property : property,
item : activeSelection.component
}
);
// addArrayItem(activeSelection.component, component[property].length - 1);
}
});
GameLib.Event.Emit(
GameLib.Event.BUILD_GUI
);
}
};
folder.add(activeSelection, 'component', selectionObject).name('select ' + property).onChange(
function(value){
if (value === 'null') {
activeSelection['component'] = null;
} else {
activeSelection['component'] = idObject[value];
}
}
).listen();
folder.add(activeSelection, 'add').name('add to ' + property);
};
GameLib.System.GUI.prototype.buildColorControl = function(folder, componentTemplate, property) {
var object = componentTemplate.template;
var tempObject = {
hexColor : object[property].toHex()
};
folder.addColor(
tempObject,
'hexColor'
).name(property).listen().onChange(
function(value) {
componentTemplate.affected.map(
function(component) {
component[property].fromHex(value);
component[property].updateInstance(property);
}
)
}
);
folder.add(
tempObject,
'hexColor'
).name(property).listen().onChange(
function(value) {
componentTemplate.affected.map(
function(component) {
component[property].fromHex(value);
component[property].updateInstance(property);
}
)
}
)
};
GameLib.System.GUI.prototype.buildSelectControl = function(folder, componentTemplate, property) {
/**
* We need to discover the constructor for this component
*/
var constructor = null;
if (componentTemplate.template[property]) {
constructor = componentTemplate.template[property].constructor;
} else {
if (componentTemplate.template.linkedObjects[property]) {
constructor = componentTemplate.template.linkedObjects[property];
}
}
var object = componentTemplate.template;
var objects = GameLib.EntityManager.Instance.queryComponents(constructor);
var idObject = {};
var options = objects.reduce(
function(result, obj) {
result[obj.name] = obj;
idObject[obj.id] = obj;
return result;
},
{
'none' : null
}
);
folder.add(
object,
property,
options
).name(property).listen().onChange(
function (value) {
var newComponent = null;
if (value !== 'null') {
newComponent = idObject[value];
}
componentTemplate.affected.map(
function(component) {
component[property] = newComponent;
component.updateInstance(property);
}
);
this.initialValue = newComponent;
}
);
};
GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate, property) {
var object = componentTemplate.template;
var listen = false;
if (componentTemplate.affected.length === 1) {
/**
* If the template only affects a single object - put the handle on this so we can listen for changes
*/
object = componentTemplate.affected[0];
listen = true;
}
var componentType = componentTemplate.componentType;
var controllers = [];
if (
GameLib.Utils.isString(object[property]) ||
GameLib.Utils.isBoolean(object[property])
) {
controllers.push(folder.add(object, property));
}
if (GameLib.Utils.isNumber(object[property])) {
var grain = 0.001;
if (object.grain) {
grain = object.grain;
}
if (property === 'systemType') {
controllers.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,
'linking' : GameLib.System.SYSTEM_TYPE_LINKING,
'physics' : GameLib.System.SYSTEM_TYPE_PHYSICS,
'custom code' : GameLib.System.SYSTEM_TYPE_CUSTOM
}
)
);
} else if (property === 'opacityType') {
controllers.push(
folder.add(
object,
property,
{
'constant': GameLib.D3.Particle.OPACITY_TYPE_CONSTANT,
'decrease': GameLib.D3.Particle.OPACITY_TYPE_DECREASE_LINEAR,
'increase': GameLib.D3.Particle.OPACITY_TYPE_INCREASE_LINEAR
}
)
);
} else if (property === 'positionOffsetType') {
controllers.push(
folder.add(
object,
property,
{
'constant': GameLib.D3.Particle.POSITION_OFFSET_TYPE_CONSTANT,
'random': GameLib.D3.Particle.POSITION_OFFSET_TYPE_RANDOM,
'function': GameLib.D3.Particle.POSITION_OFFSET_TYPE_FUNCTION
}
)
);
} else if (property === 'directionType') {
controllers.push(
folder.add(
object,
property,
{
'constant': GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT,
'random': GameLib.D3.Particle.DIRECTION_TYPE_RANDOM,
'random normalized': GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED,
'function': GameLib.D3.Particle.DIRECTION_TYPE_FUNCTION
}
)
);
} else if (property === 'speedType') {
controllers.push(
folder.add(
object,
property,
{
'constant': GameLib.D3.Particle.SPEED_TYPE_CONSTANT,
'linear': GameLib.D3.Particle.SPEED_TYPE_LINEAR,
'exponential': GameLib.D3.Particle.SPEED_TYPE_EXPONENTIAL,
'logarithmic': GameLib.D3.Particle.SPEED_TYPE_LOGARITHMIC,
'1 / log': GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_LOG,
'exp' : GameLib.D3.Particle.SPEED_TYPE_EXP,
'1 / exp' : GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_EXP
}
)
);
} else if (property === 'scaleType') {
controllers.push(
folder.add(
object,
property,
{
'constant': GameLib.D3.Particle.SCALE_TYPE_CONSTANT,
'linear': GameLib.D3.Particle.SCALE_TYPE_LINEAR,
'exponential': GameLib.D3.Particle.SCALE_TYPE_EXPONENTIAL,
'random': GameLib.D3.Particle.SCALE_TYPE_RANDOM,
'random (x = y)': GameLib.D3.Particle.SCALE_TYPE_RANDOM_X_EQUALS_Y,
'function': GameLib.D3.Particle.SCALE_TYPE_FUNCTION
}
)
);
} else if (property === 'rotationType') {
controllers.push(
folder.add(
object,
property,
{
'constant': GameLib.D3.Particle.ROTATION_TYPE_CONSTANT,
'random': GameLib.D3.Particle.ROTATION_TYPE_RANDOM,
'function': GameLib.D3.Particle.ROTATION_TYPE_FUNCTION
}
)
);
} else if (property === 'broadphaseType') {
controllers.push(
folder.add(
object,
property,
{
'naive': GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE,
'grid': GameLib.D3.Image.BROADPHASE_TYPE_GRID,
'sap': GameLib.D3.Image.BROADPHASE_TYPE_SAP
}
)
);
} else if (property === 'solverType') {
controllers.push(
folder.add(
object,
property,
{
'gs': GameLib.D3.Solver.GS_SOLVER,
'split': GameLib.D3.Solver.SPLIT_SOLVER
}
)
);
} else if (property === 'meshType') {
controllers.push(
folder.add(
object,
property,
{
'normal' : GameLib.D3.Mesh.MESH_TYPE_NORMAL,
'curve' : GameLib.D3.Mesh.MESH_TYPE_CURVE,
'skinned' : GameLib.D3.Mesh.MESH_TYPE_SKINNED,
'plane' : GameLib.D3.Mesh.MESH_TYPE_PLANE,
'sphere' : GameLib.D3.Mesh.MESH_TYPE_SPHERE,
'box' : GameLib.D3.Mesh.MESH_TYPE_BOX,
'cylinder' : GameLib.D3.Mesh.MESH_TYPE_CYLINDER,
'text' : GameLib.D3.Mesh.MESH_TYPE_TEXT
}
)
);
} else if (property === 'cameraType') {
controllers.push(
folder.add(
object,
property,
{
'perspective' : GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE,
'orthographic' : GameLib.D3.Camera.CAMERA_TYPE_ORTHOGONAL
}
)
);
} else if (property === 'materialType') {
controllers.push(
folder.add(
object,
property,
{
'standard': GameLib.D3.Material.MATERIAL_TYPE_STANDARD,
'basic': GameLib.D3.Material.MATERIAL_TYPE_BASIC,
'phong': GameLib.D3.Material.MATERIAL_TYPE_PHONG,
'points': GameLib.D3.Material.MATERIAL_TYPE_POINTS,
'toon': GameLib.D3.Material.MATERIAL_TYPE_TOON,
'line basic' : GameLib.D3.Material.MATERIAL_TYPE_LINE_BASIC
}
)
);
} else if (property === 'side') {
controllers.push(
folder.add(
object,
property,
{
'double': GameLib.D3.Material.TYPE_DOUBLE_SIDE,
'front': GameLib.D3.Material.TYPE_FRONT_SIDE,
'back': GameLib.D3.Material.TYPE_BACK_SIDE
}
)
);
} else if (property === 'combine') {
controllers.push(
folder.add(
object,
property,
{
'multiply': GameLib.D3.Material.TYPE_MULTIPLY_OPERATION,
'mix': GameLib.D3.Material.TYPE_MIX_OPERATION,
'add': GameLib.D3.Material.TYPE_ADD_OPERATION
}
)
);
} else if (property === 'vertexColors') {
controllers.push(
folder.add(
object,
property,
{
'none': GameLib.D3.Material.TYPE_NO_COLORS,
'face': GameLib.D3.Material.TYPE_FACE_COLORS,
'vertex': GameLib.D3.Material.TYPE_VERTEX_COLORS
}
)
);
} else if (property === 'blending') {
controllers.push(
folder.add(
object,
property,
{
'none': GameLib.D3.Material.TYPE_NO_BLENDING,
'normal': GameLib.D3.Material.TYPE_NORMAL_BLENDING,
'additive': GameLib.D3.Material.TYPE_ADDITIVE_BLENDING,
'subtractive': GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING,
'multiply': GameLib.D3.Material.TYPE_MULTIPLY_BLENDING,
'custom': GameLib.D3.Material.TYPE_CUSTOM_BLENDING
}
)
);
} else if (property === 'blendSrc') {
controllers.push(
folder.add(
object,
property,
{
'zero': GameLib.D3.Material.TYPE_ZERO_FACTOR,
'one': GameLib.D3.Material.TYPE_ONE_FACTOR,
'source color': GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR,
'one minus source color': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR,
'source alpha': GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR,
'one minus source alpha': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR,
'destination alpha': GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR,
'one minus destination alpha': GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR,
'destination color': GameLib.D3.Material.TYPE_DST_COLOR_FACTOR,
'one minus destination color': GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR,
'source alpha saturate': GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR
}
)
);
} else if (property === 'blendDst') {
controllers.push(
folder.add(
object,
property,
{
'zero': GameLib.D3.Material.TYPE_ZERO_FACTOR,
'one': GameLib.D3.Material.TYPE_ONE_FACTOR,
'source color': GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR,
'one minus source color': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR,
'source alpha': GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR,
'one minus source alpha': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR,
'destination alpha': GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR,
'one minus destination alpha': GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR,
'destination color': GameLib.D3.Material.TYPE_DST_COLOR_FACTOR,
'one minus destination color': GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR,
'source alpha saturate': GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR
}
)
);
} else if (property === 'blendEquation') {
controllers.push(
folder.add(
object,
property,
{
'add': GameLib.D3.Material.TYPE_ADD_EQUATION,
'subtract': GameLib.D3.Material.TYPE_SUBTRACT_EQUATION,
'reverse subtract': GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION,
'min': GameLib.D3.Material.TYPE_MIN_EQUATION,
'max': GameLib.D3.Material.TYPE_MAX_EQUATION
}
)
);
} else if (property === 'depthFunc') {
controllers.push(
folder.add(
object,
property,
{
'never': GameLib.D3.Material.TYPE_NEVER_DEPTH,
'always': GameLib.D3.Material.TYPE_ALWAYS_DEPTH,
'less depth': GameLib.D3.Material.TYPE_LESS_DEPTH,
'less equal depth': GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH,
'equal depth': GameLib.D3.Material.TYPE_EQUAL_DEPTH,
'greated equal depth': GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH,
'greated depth': GameLib.D3.Material.TYPE_GREATER_DEPTH,
'not equal depth': GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH
}
)
);
} else if (property === 'wrapS') {
controllers.push(
folder.add(
object,
property,
{
'repeat': GameLib.D3.Texture.TYPE_REPEAT_WRAPPING,
'clamp': GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING,
'mirrored repeat': GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING
}
)
);
} else if (property === 'wrapT') {
controllers.push(
folder.add(
object,
property,
{
'repeat': GameLib.D3.Texture.TYPE_REPEAT_WRAPPING,
'clamp': GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING,
'mirrored repeat': GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING
}
)
);
} else if (property === 'format') {
controllers.push(
folder.add(
object,
property,
{
'alpha': GameLib.D3.Texture.TYPE_ALPHA_FORMAT,
'rgb': GameLib.D3.Texture.TYPE_RGB_FORMAT,
'rgba': GameLib.D3.Texture.TYPE_RGBA_FORMAT,
'luminance': GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT,
'luminance alpha': GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT,
'depth': GameLib.D3.Texture.TYPE_DEPTH_FORMAT
}
)
);
} else if (property === 'mapping') {
controllers.push(
folder.add(
object,
property,
{
'uv': GameLib.D3.Texture.TYPE_UV_MAPPING,
'cube reflection': GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING,
'cube refraction': GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING,
'equi rectangular reflection': GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING,
'equi rectangular refraction': GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING,
'spherical reflection': GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING,
'cube uv reflection': GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING,
'cube uv refraction': GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING
}
)
);
} else if (property === 'magFilter') {
controllers.push(
folder.add(
object,
property,
{
'nearest': GameLib.D3.Texture.TYPE_NEAREST_FILTER,
'nearest mipmap nearest': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER,
'nearest mipmap linear': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER,
'linear': GameLib.D3.Texture.TYPE_LINEAR_FILTER,
'linear mipmap nearest': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER,
'linear mipmap linear': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER
}
)
);
} else if (property === 'minFilter') {
controllers.push(
folder.add(
object,
property,
{
'nearest': GameLib.D3.Texture.TYPE_NEAREST_FILTER,
'nearest mipmap nearest': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER,
'nearest mipmap linear': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER,
'linear': GameLib.D3.Texture.TYPE_LINEAR_FILTER,
'linear mipmap nearest': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER,
'linear mipmap linear': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER
}
)
);
} else if (componentType === GameLib.Component.COMPONENT_TEXTURE && property === 'typeId') {
controllers.push(
folder.add(
object,
property,
{
'normal': GameLib.D3.Texture.TEXTURE_TYPE_NORMAL,
'cube': GameLib.D3.Texture.TEXTURE_TYPE_CUBE,
'canvas': GameLib.D3.Texture.TEXTURE_TYPE_CANVAS
}
)
);
} else if (property === 'textureType') {
controllers.push(
folder.add(
object,
property,
{
'unsigned byte': GameLib.D3.Texture.TYPE_UNSIGNED_BYTE,
'byte': GameLib.D3.Texture.TYPE_BYTE,
'short': GameLib.D3.Texture.TYPE_SHORT,
'unsigned short': GameLib.D3.Texture.TYPE_UNSIGNED_SHORT,
'int': GameLib.D3.Texture.TYPE_INT,
'unsigned int': GameLib.D3.Texture.TYPE_UNSIGNED_INT,
'float': GameLib.D3.Texture.TYPE_FLOAT,
'half float': GameLib.D3.Texture.TYPE_HALF_FLOAT
}
)
);
} else if (property === 'encoding') {
controllers.push(
folder.add(
object,
property,
{
'linear': GameLib.D3.Texture.TYPE_LINEAR_ENCODING,
'srgb': GameLib.D3.Texture.TYPE_SRGB_ENCODING,
'gamma': GameLib.D3.Texture.TYPE_GAMMA_ENCODING,
'rgbe': GameLib.D3.Texture.TYPE_RGBE_ENCODING,
'log luv': GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING,
'rgbm7': GameLib.D3.Texture.TYPE_RGBM7_ENCODING,
'rgbm16': GameLib.D3.Texture.TYPE_RGBM16_ENCODING,
'rgbd': GameLib.D3.Texture.TYPE_RGBD_ENCODING
}
)
);
} else if (property === 'lightType') {
controllers.push(
folder.add(
object,
property,
{
'ambient': GameLib.D3.Light.LIGHT_TYPE_AMBIENT,
'directional': GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL,
'spot': GameLib.D3.Light.LIGHT_TYPE_SPOT,
'point': GameLib.D3.Light.LIGHT_TYPE_POINT
}
)
);
} else if (property === 'eventId') {
var options = {};
for (var i = 0; i < 200; i++) {
try {
options[GameLib.Event.GetEventName(i)] = i;
} catch (error) {
}
}
controllers.push(
folder.add(
object,
property,
options
)
);
} else if (property === 'functionType') {
controllers.push(
folder.add(
object,
property,
{
'rotation': GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_ROTATION,
'translation': GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_TRANSLATION,
'scale': GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_SCALE
}
)
);
} else {
/**
* Try to guess a scale for this property
*/
if (
property === 'opacity' ||
property === 'opacityFactor' ||
property === 'metalness' ||
property === 'roughness' ||
property === 'volume'
) {
controllers.push(folder.add(object, property, 0, 1.0, 0.001));
} else if (
property === 'shininess' ||
property === 'fov'
) {
controllers.push(folder.add(object, property, -255, 255, 1));
} else if (
property === 'aspect' ||
property === 'wireframeLineWidth' ||
property === 'lineWidth'
) {
controllers.push(folder.add(object, property, 0, 5, 0.001));
} else if (
property === 'bumpScale' ||
property === 'normalScale' ||
property === 'displacementScale' ||
property === 'heightMapScale' ||
property === 'intensity'
) {
controllers.push(folder.add(object, property, -10, 10, 0.001));
} else if (
property === 'minX' ||
property === 'minY' ||
property === 'minZ' ||
property === 'maxX' ||
property === 'maxY' ||
property === 'maxZ' ||
property === 'offsetX'
) {
controllers.push(folder.add(object, property, -1000, 1000, 0.01));
} else if (
property === 'widthSegments' ||
property === 'radiusSegments' ||
property === 'heightSegments' ||
property === 'particlesPerSecond'
) {
controllers.push(folder.add(object, property, 1, 1000, 1));
} else if (
property === 'width' ||
property === 'height' ||
property === 'depth' ||
property === 'radius'
) {
controllers.push(folder.add(object, property, 0, 1000, 0.1));
} else if (
property === 'near' ||
property === 'distanceGrain' ||
property === 'envMapIntensity'
) {
controllers.push(folder.add(object, property, -10, 100, 0.001));
} else if (
property === 'bumpScale'
) {
controllers.push(folder.add(object, property, 0, 20, 0.001));
} else if (
property === 'heightOffset' ||
property === 'rotationFactor'
) {
controllers.push(folder.add(object, property, -100, 100, 0.001));
} else if (
property === 'friction'
) {
controllers.push(folder.add(object, property, 0, 1000, 0.01));
} else if (
property === 'radiusTop' ||
property === 'radiusBottom'
) {
controllers.push(folder.add(object, property, 0, 100, 0.1));
} else if (
property === 'mass'
) {
controllers.push(folder.add(object, property, 0, 1000, 0.1));
} else if (
property === 'sensitivity'
) {
controllers.push(folder.add(object, property, 1, 50, 1));
} else if (
property === 'density'
) {
controllers.push(folder.add(object, property, 0, 1, 0.0001));
} else if (
property === 'thetaLength' ||
property === 'angle'
) {
controllers.push(folder.add(object, property, -Math.PI * 2, Math.PI * 2, 0.01));
} else {
controllers.push(folder.add(object, property, -1000, 1000, 0.1));
}
}
}
controllers.map(
function(controller) {
if (property === 'name') {
controller.onFinishChange(
function(__handle, __folder) {
return function(value) {
componentTemplate.affected.map(
function(component){
component[property] = value;
component.updateInstance(property);
}
);
var li = __folder.domElement.getElementsByClassName('title')[0];
li.innerHTML = value;
}
}(controller, folder)
);
} else {
controller.onChange(
function (value) {
if (typeof this.initialValue === 'number') {
value = Number(value);
}
componentTemplate.affected.map(
function(component){
component[property] = value;
component.updateInstance(property);
}
);
}
);
}
if (listen) {
controller.listen();
}
}
);
};
/**
* Push the mesh to our backup components, if in exclusiveMode (menu at top is selected),
* otherwise, just to our normal components
* @param data
*/
GameLib.System.GUI.prototype.meshSelected = function(data) {
if (this.exclusiveMode) {
GameLib.Utils.PushUnique(this.backupComponents, data.mesh);
} else {
GameLib.Utils.PushUnique(this.components, data.mesh);
}
};
/**
* Same as selected above, but removes the mesh from the components
* @param data
*/
GameLib.System.GUI.prototype.meshDeslected = function(data) {
var index = -1;
if (this.exclusiveMode) {
index = this.backupComponents.indexOf(data.mesh);
if (index !== -1) {
this.backupComponents.splice(index, 1);
}
} else {
index = this.components.indexOf(data.mesh);
if (index !== -1) {
this.components.splice(index, 1);
}
}
};
/**
* This function responds to the BUILD_GUI event, data contains the components to build a GUI for data.
*
* If we send data with components - go into exclusive mode, backup the currently selected components and rebuild the gui
*
* If we send data without components - go out of exclusive mode, restore the backup of the currently selected components
* and rebuild based on the meshes
*
* If we don't send any data (null or undefined) - some parameters changed and just rebuild the gui.
*
* @param data
*/
GameLib.System.GUI.prototype.buildGUI = function(data) {
this.guis.map(function(gui){
/**
* First, start fresh - remove all folders
*/
gui.instance.destroy();
gui.removeAllFolders();
// gui.domElement.instance.parentElement.appendChild(gui.instance.domElement);
if (data) {
if (data.components) {
/**
* Check if we are not already in exclusive mode, because we only want to make a backup if
* it does not already exist
*/
if (!this.exclusiveMode) {
this.exclusiveMode = true;
/**
* Backup the current selection
*/
this.backupComponents = this.components.map(
function(component) {
return component;
}
);
}
this.components = data.components.map(
function(component) {
return component;
}
);
} else {
if (this.exclusiveMode) {
this.exclusiveMode = false;
/**
* Time to restore the backup
*/
this.components = this.backupComponents.map(
function(component) {
return component;
}
)
} else {
console.log('we are already not in mesh select mode - not doing anything with the backup');
}
}
}
/**
* For all mesh components - (if not in exclusive mode) - try to discover all materials, textures, etc
*/
if (!this.exclusiveMode) {
/**
* We first remove everything which is not a Mesh
*/
this.components = this.components.filter(
function (component) {
return (component instanceof GameLib.D3.Mesh);
}
);
}
/**
* Check if we have components to build a GUI for
*/
if (GameLib.Utils.UndefinedOrNull(this.components.length) || this.components.length < 1) {
// console.log('no components selected');
return;
}
/**
* Now continue to discover materials, textures, images etc. children of this component
*/
if (!this.exclusiveMode) {
this.components = this.components.reduce(
function(result, component) {
var components = component.getChildrenComponents();
GameLib.Utils.PushUnique(result, component);
components.map(function(component){
GameLib.Utils.PushUnique(result, component);
});
return result;
}.bind(this),
[]
);
}
/**
* Sort the components by component type
*/
this.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 = this.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 : this.components[0].componentType,
components : []
}
]
);
/**
* We have all the components split into groups - now add the individual components
*/
this.components.map(
function(component) {
/**
* Check for possible duplicates
* @type {boolean}
*/
var duplicate = false;
componentGroups.map(function(componentGroup){
if (
componentGroup.componentType === component.componentType &&
componentGroup.components.length === 1 &&
componentGroup.components[0] === component
) {
duplicate = true;
}
});
if (!duplicate) {
GameLib.Utils.PushUnique(
componentGroups,
{
componentType : component.componentType,
components : [component]
}
);
}
}
);
/**
* componentGroups should now contain the whole list of stuff we want to build GUI for.
*/
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 ||
result.template[property] instanceof GameLib.Quaternion
) {
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) + ' (All Selected (' + componentTemplate.affected.length + '))';
} else {
name = componentTemplate.template.name;
}
var folder = gui.addFolder(name);
if (!folder) {
return;
}
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;
}
/**
* We only want to affect runtime vectors because their onchange will execute updateInstance()
*/
if (
componentTemplate.template[templateProperty] instanceof GameLib.Vector2 ||
componentTemplate.template[templateProperty] instanceof GameLib.Vector3 ||
componentTemplate.template[templateProperty] instanceof GameLib.Vector4
) {
this.buildVectorControl(folder, componentTemplate, templateProperty);
continue;
}
if (componentTemplate.template[templateProperty] instanceof GameLib.Quaternion) {
this.buildQuaternionControl(folder, componentTemplate, templateProperty);
}
if (
templateProperty === 'parentEntity' ||
templateProperty === 'parentWorld' ||
templateProperty === 'parentMesh' ||
templateProperty === 'parentScene'
) {
this.buildParentSelectionControl(folder, componentTemplate, templateProperty);
continue;
}
if (componentTemplate.template[templateProperty] instanceof Array) {
if (
templateProperty === 'vertices' ||
templateProperty === 'faces'
) {
continue;
}
if (
componentTemplate.template.linkedObjects &&
componentTemplate.template.linkedObjects[templateProperty] instanceof Array
) {
this.buildArrayManagerControl(folder, componentTemplate, templateProperty);
}
continue;
}
if (componentTemplate.template[templateProperty] instanceof GameLib.Color) {
this.buildColorControl(folder, componentTemplate, templateProperty);
continue;
}
if (typeof componentTemplate.template[templateProperty] === 'object') {
if (
componentTemplate.template[templateProperty] instanceof GameLib.Component ||
(
componentTemplate.template.linkedObjects &&
componentTemplate.template.linkedObjects[templateProperty]
)
) {
this.buildSelectControl(folder, componentTemplate, templateProperty)
} else {
//TODO: maybe start including some other types of objects
//console.log('ignored : ' + templateProperty);
}
continue;
}
this.buildControl(folder, componentTemplate, templateProperty);
// 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);
// }
}
}
}.bind(this)
);
}.bind(this));
};
GameLib.System.GUI.prototype.meshDeleted = function(data) {
data.meshes.map(function(mesh){
this.meshDeslected({
mesh : mesh
})
}.bind(this));
this.buildGUI(null);
};
GameLib.System.GUI.prototype.removeComponent = function(data) {
var index = this.backupComponents.indexOf(data.component);
if (index !== -1) {
this.backupComponents.splice(index, 1);
}
index = this.components.indexOf(data.component);
if (index !== -1) {
this.components.splice(index, 1);
}
};
GameLib.System.GUI.prototype.newEntity = function(data) {
};
GameLib.System.GUI.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
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.componentRemovedSubscription.remove();
this.guis = [];
};
/**
* System takes care of updating all the entities (based on their component data)
* @param apiSystem GameLib.API.System
* @param graphics
* @constructor
*/
GameLib.System.Input = function(
apiSystem,
graphics
) {
GameLib.System.call(
this,
apiSystem
);
this.graphics = graphics;
this.graphics.isNotThreeThrow();
this.selectAll = false;
this.controlLeft = false;
this.sensitivityCounter = 0;
this.editorControls = [];
this.touchControls = [];
this.keyboardControls = [];
this.mouseControls = [];
/**
* Touch Controls
* @type {null}
*/
this.touchStart = null;
this.touchMove = null;
this.touchEnd = null;
this.touchCancel = null;
/**
* Keyboard Controls
* @type {null}
*/
this.keyboardKeyUp = null;
this.keyboardKeyDown = null;
/**
* Mouse Controls
* @type {null}
*/
this.mouseDown = null;
this.mouseMove = null;
this.mouseWheel = null;
this.mouseUp = null;
/**
* Editor Controls
* @type {null}
*/
this.keyDown = null;
this.keyUp = null;
this.mouseDownEdit = null;
this.mouseMoveEdit = null;
this.mouseWheelEdit = null;
this.mouseUpEdit = null;
this.delayedInstanceEncounteredSubscription = null;
this.instanceCreatedSubscription = null;
this.removeComponentSubscription = null;
this.mouse = new GameLib.Mouse(
graphics
)
};
GameLib.System.Input.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Input.prototype.constructor = GameLib.System.Input;
/**
*
*/
GameLib.System.Input.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.editorControls = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Controls.Editor);
this.touchControls = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Controls.Touch);
this.keyboardControls = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Controls.Keyboard);
this.mouseControls = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Controls.Mouse);
this.instanceCreatedSubscription = GameLib.Event.Subscribe(
GameLib.Event.INSTANCE_CREATED,
this.instanceCreated.bind(this)
);
this.removeComponentSubscription = GameLib.Event.Subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent.bind(this)
);
this.delayedInstanceEncounteredSubscription = GameLib.Event.Subscribe(
GameLib.Event.DELAYED_INSTANCE_ENCOUNTERED,
this.delayedInstanceEncountered.bind(this)
);
/**
* If we have touch controls - inject them first so we can override editor controls if necessary
*/
this.registerTouchControls();
this.registerKeyboardControls();
this.registerMouseControls();
this.registerEditorControls();
};
/**
*
*/
GameLib.System.Input.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.instanceCreatedSubscription.remove();
this.removeComponentSubscription.remove();
this.delayedInstanceEncounteredSubscription.remove();
this.deRegisterEditorControls();
this.deRegisterTouchControls();
this.deRegisterKeyboardControls();
this.deRegisterMouseControls();
this.editorControls = [];
this.touchControls = [];
this.keyboardControls = [];
this.mouseControls = [];
};
/**
* From now on we want to track everything about a component, only from the systems that are active
* @param data
*/
GameLib.System.Input.prototype.instanceCreated = function(data) {
if (data.component instanceof GameLib.D3.Controls.Editor) {
if (this.editorControls.length > 0) {
console.log('ignoring multiple editor controls')
} else {
this.editorControls.push(data.component);
this.registerEditorControls();
}
}
if (data.component instanceof GameLib.D3.Controls.Touch) {
if (this.touchControls.length > 0) {
console.log('ignoring multiple touch controls')
} else {
this.touchControls.push(data.component);
this.registerTouchControls();
}
}
if (data.component instanceof GameLib.D3.Controls.Keyboard) {
if (this.keyboardControls.length > 0) {
console.log('ignoring multiple keyboard controls')
} else {
this.keyboardControls.push(data.component);
this.registerKeyboardControls();
}
}
if (data.component instanceof GameLib.D3.Controls.Mouse) {
if (this.mouseControls.length > 0) {
console.log('ignoring multiple mouse controls')
} else {
this.mouseControls.push(data.component);
this.registerMouseControls();
}
}
};
/**
* Removes a particle engine from this system
* @param data
*/
GameLib.System.Input.prototype.removeComponent = function(data) {
if (data.component instanceof GameLib.D3.Controls.Editor) {
var index = this.editorControls.indexOf(data.component);
if (index !== -1) {
console.log('removing editor controls from system');
this.deRegisterEditorControls();
this.editorControls.splice(index, 1);
} else {
console.log('failed to find the editor controls in the system - probably it was ignored - ' + data.component.name);
}
}
};
/**
* Delayed Instance - we need to check if editControls will block the loading process (since only one will be created)
* @param data
*/
GameLib.System.Input.prototype.delayedInstanceEncountered = function(data) {
if (data.component instanceof GameLib.D3.Controls.Editor) {
if (this.editorControls.length === 0) {
/**
* We need to register these controls so instance creation can continue
*/
this.editorControls.push(data.component);
this.registerEditorControls();
} else {
/**
* There are already another editor controls, these ones will never get created, we need to
* notify our linking system of this problem so loading can continue
*/
data.component.createInstance();
}
}
};
GameLib.System.Input.prototype.registerTouchControls = function() {
if (this.touchControls.length !== 1) {
return;
}
var touchControl = this.touchControls[0];
this.touchSensitivity = touchControl.sensitivity;
this.touchStart = this.onTouchStart.bind(this);
this.touchMove = this.onTouchMove.bind(this);
this.touchEnd = this.onTouchEnd.bind(this);
this.touchCancel = this.onTouchCancel.bind(this);
touchControl.domElement.instance.addEventListener(
'touchstart',
this.touchStart,
false
);
touchControl.domElement.instance.addEventListener(
'touchmove',
this.touchMove,
false
);
touchControl.domElement.instance.addEventListener(
'touchend',
this.touchEnd,
false
);
touchControl.domElement.instance.addEventListener(
'touchcancel',
this.touchCancel,
false
);
};
GameLib.System.Input.prototype.registerKeyboardControls = function() {
if (this.keyboardControls.length !== 1) {
return;
}
var keyboardControl = this.keyboardControls[0];
this.keyboardKeyUp = this.onKeyboardKeyUp.bind(this);
this.keyboardKeyDown = this.onKeyboardKeyDown.bind(this);
keyboardControl.domElement.instance.addEventListener(
'keyup',
this.keyboardKeyUp,
false
);
keyboardControl.domElement.instance.addEventListener(
'keydown',
this.keyboardKeyDown,
false
);
};
GameLib.System.Input.prototype.registerMouseControls = function() {
if (this.mouseControls.length !== 1) {
return;
}
var mouseControl = this.mouseControls[0];
this.mouseDown = this.onMouseDown.bind(this);
this.mouseMove = this.onMouseMove.bind(this);
this.mouseWheel = this.onMouseWheel.bind(this);
this.mouseUp = this.onMouseUp.bind(this);
mouseControl.domElement.instance.addEventListener(
'mousedown',
this.mouseDown,
false
);
mouseControl.domElement.instance.addEventListener(
'mousemove',
this.mouseMove,
false
);
mouseControl.domElement.instance.addEventListener(
'wheel',
this.mouseWheel,
false
);
mouseControl.domElement.instance.addEventListener(
'mouseup',
this.mouseUp,
false
);
};
GameLib.System.Input.prototype.registerEditorControls = function() {
if (this.editorControls.length !== 1) {
return;
}
var editorControl = this.editorControls[0];
/**
* If we already have mouse controls, we don't want to add another event listener onto the DOM
*/
this.mouseDownEdit = this.onMouseDownEdit.bind(this);
this.mouseMoveEdit = this.onMouseMoveEdit.bind(this);
editorControl.domElement.instance.addEventListener(
'mousedown',
this.mouseDownEdit,
false
);
editorControl.domElement.instance.addEventListener(
'mousemove',
this.mouseMoveEdit,
false
);
/**
* If we already have keyboard controls, we don't want to add another event listener onto the DOM
*/
if (this.keyboardControls.length > 0) {
/**
* Do Nothing
*/
} else {
this.keyDown = this.onKeyDown.bind(this);
this.keyUp = this.onKeyUp.bind(this);
editorControl.domElement.instance.addEventListener(
'keydown',
this.keyDown,
false
);
editorControl.domElement.instance.addEventListener(
'keyup',
this.keyUp,
false
);
}
editorControl.createInstance();
this.mouseWheelEdit = this.onMouseWheelEdit.bind(this);
this.mouseUpEdit = this.onMouseUpEdit.bind(this);
editorControl.domElement.instance.addEventListener(
'wheel',
this.mouseWheelEdit,
false
);
editorControl.domElement.instance.addEventListener(
'mouseup',
this.mouseUpEdit,
false
);
};
GameLib.System.Input.prototype.deRegisterEditorControls = function() {
if (this.editorControls.length !== 1) {
return;
}
var editorControl = this.editorControls[0];
editorControl.domElement.instance.removeEventListener(
'mousedown',
this.mouseDownEdit,
false
);
editorControl.domElement.instance.removeEventListener(
'mousemove',
this.mouseMoveEdit,
false
);
if (this.keyboardControls.length < 1) {
editorControl.domElement.instance.removeEventListener(
'keydown',
this.keyDown,
false
);
editorControl.domElement.instance.removeEventListener(
'keyup',
this.keyUp,
false
);
}
editorControl.instance.dispose();
editorControl.domElement.instance.removeEventListener(
'wheel',
this.mouseWheelEdit,
false
);
editorControl.domElement.instance.removeEventListener(
'mouseup',
this.mouseUpEdit,
false
);
};
GameLib.System.Input.prototype.deRegisterTouchControls = function() {
if (this.touchControls.length !== 1) {
return;
}
var touchControl = this.touchControls[0];
touchControl.domElement.instance.removeEventListener(
'touchstart',
this.touchStart,
false
);
touchControl.domElement.instance.removeEventListener(
'touchmove',
this.touchMove,
false
);
touchControl.domElement.instance.removeEventListener(
'touchend',
this.touchEnd,
false
);
touchControl.domElement.instance.removeEventListener(
'touchcancel',
this.touchCancel,
false
);
};
GameLib.System.Input.prototype.deRegisterKeyboardControls = function() {
if (this.keyboardControls.length !== 1) {
return;
}
var keyboardControl = this.keyboardControls[0];
keyboardControl.domElement.instance.removeEventListener(
'keydown',
this.keyboardKeyDown,
false
);
keyboardControl.domElement.instance.removeEventListener(
'keyup',
this.keyboardKeyUp,
false
);
};
GameLib.System.Input.prototype.deRegisterMouseControls = function() {
if (this.mouseControls.length !== 1) {
return;
}
var mouseControl = this.mouseControls[0];
mouseControl.domElement.instance.removeEventListener(
'mousedown',
this.mouseDown,
false
);
mouseControl.domElement.instance.removeEventListener(
'mousemove',
this.mouseMove,
false
);
mouseControl.domElement.instance.removeEventListener(
'wheel',
this.mouseWheel,
false
);
mouseControl.domElement.instance.removeEventListener(
'mouseup',
this.mouseUp,
false
);
};
GameLib.System.Input.prototype.onKeyboardKeyUp = function(event) {
GameLib.Event.Emit(
GameLib.Event.KEY_DOWN,
{
code : event.code
}
);
};
GameLib.System.Input.prototype.onKeyboardKeyDown = function(event) {
GameLib.Event.Emit(
GameLib.Event.KEY_UP,
{
code : event.code
}
);
};
GameLib.System.Input.prototype.onTouchStart = function(event) {
this.sensitivityCounter = 0;
this.touches = {};
for (var t = 0; t < event.touches.length; t++) {
this.touches[event.touches[t].identifier] = {
left : 0,
right : 0,
up : 0,
down : 0,
lastTouchX : event.touches[t].pageX,
lastTouchY : event.touches[t].pageY,
pageX : event.touches[t].pageX,
pageY : event.touches[t].pageY,
cancelled : false,
ended : false
};
}
this.touches.event = event;
GameLib.Event.Emit(
GameLib.Event.TOUCH_START,
this.touches
)
};
GameLib.System.Input.prototype.onTouchMove = function (event) {
this.sensitivityCounter++;
var id = null;
var leftTouch = null;
var rightTouch = null;
var bottomTouch = null;
var topTouch = null;
var inward = false;
var outward = false;
var pinch = false;
var zoom = false;
for (var t = 0; t < event.changedTouches.length; t++) {
id = event.changedTouches[t].identifier;
if (this.touches[id]) {
var diffX = Math.abs(this.touches[id].lastTouchX - event.changedTouches[t].pageX);
var diffY = Math.abs(this.touches[id].lastTouchY - event.changedTouches[t].pageY);
var left = 0;
var right = 0;
var up = 0;
var down = 0;
if (this.touches[id].lastTouchX < event.changedTouches[t].pageX) {
right += diffX;
}
if (this.touches[id].lastTouchX > event.changedTouches[t].pageX) {
left += diffX;
}
if (this.touches[id].lastTouchY > event.changedTouches[t].pageY) {
up += diffY;
}
if (this.touches[id].lastTouchY < event.changedTouches[t].pageY) {
down += diffY;
}
this.touches[id].right = right;
this.touches[id].left = left;
this.touches[id].up = up;
this.touches[id].down = down;
this.touches[id].lastTouchX = event.changedTouches[t].pageX;
this.touches[id].lastTouchY = event.changedTouches[t].pageY;
this.touches[id].pageX = event.changedTouches[t].pageX;
this.touches[id].pageY = event.changedTouches[t].pageY;
}
}
if (event.changedTouches.length === 2) {
if (event.changedTouches[0].pageX < event.changedTouches[1].pageX) {
leftTouch = this.touches[event.changedTouches[0].identifier];
rightTouch = this.touches[event.changedTouches[1].identifier];
} else {
leftTouch = this.touches[event.changedTouches[1].identifier];
rightTouch = this.touches[event.changedTouches[0].identifier];
}
if (event.changedTouches[0].pageY < event.changedTouches[1].pageY) {
bottomTouch = this.touches[event.changedTouches[1].identifier];
topTouch = this.touches[event.changedTouches[0].identifier];
} else {
bottomTouch = this.touches[event.changedTouches[0].identifier];
topTouch = this.touches[event.changedTouches[1].identifier];
}
}
if (leftTouch && leftTouch.left && rightTouch && rightTouch.right) {
outward = true;
}
if (leftTouch && leftTouch.right && rightTouch && rightTouch.left) {
inward = true;
}
if (bottomTouch && bottomTouch.up && topTouch && topTouch.down) {
pinch = true;
}
if (bottomTouch && bottomTouch.down && topTouch && topTouch.up) {
zoom = true;
}
this.touches.event = event;
this.touches.meta = {
inward : inward,
outward : outward,
pinch : pinch,
zoom : zoom
};
if (this.sensitivityCounter >= this.touchSensitivity) {
this.sensitivityCounter = 0;
GameLib.Event.Emit(
GameLib.Event.TOUCH_MOVE,
this.touches
);
}
};
GameLib.System.Input.prototype.onTouchCancel = function(event) {
this.sensitivityCounter = 0;
for (var t = 0; t < event.changedTouches.length; t++) {
this.touches[event.changedTouches[t].identifier].cancelled = true;
this.touches[event.changedTouches[t].identifier].event = event;
GameLib.Event.Emit(
GameLib.Event.TOUCH_CANCEL,
this.touches[event.changedTouches[t].identifier]
);
delete this.touches[event.changedTouches[t].identifier];
}
};
GameLib.System.Input.prototype.onTouchEnd = function(event) {
this.sensitivityCounter = 0;
for (var t = 0; t < event.changedTouches.length; t++) {
this.touches[event.changedTouches[t].identifier].ended = true;
this.touches[event.changedTouches[t].identifier].event = event;
GameLib.Event.Emit(
GameLib.Event.TOUCH_END,
this.touches[event.changedTouches[t].identifier]
);
delete this.touches[event.changedTouches[t].identifier];
}
};
GameLib.System.Input.prototype.onKeyDown = function(event) {
console.log('input system emitted keypress ' + event.code);
GameLib.Event.Emit(
GameLib.Event.KEY_DOWN,
{
code : event.code
}
);
var meshes = null;
if (event.code === 'Delete') {
meshes = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Mesh]);
var deletedMeshes = [];
meshes.map(
function(mesh) {
if (mesh.selected) {
deletedMeshes.push(mesh);
mesh.removeHelper();
var scene = mesh.parentScene;
scene.removeObject(mesh);
scene.buildIdToObject();
}
}.bind(this)
);
GameLib.Event.Emit(
GameLib.Event.REMOVE_MESH,
{
meshes : deletedMeshes
}
);
}
if (event.code === 'ControlLeft') {
this.controlLeft = true;
}
if (event.code === 'KeyA') {
this.selectAll = !this.selectAll;
meshes = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Mesh]);
meshes.map(function(mesh){
if (this.selectAll) {
this.selectMesh(mesh);
} else {
this.deSelectMesh(mesh);
}
}.bind(this));
GameLib.Event.Emit(
GameLib.Event.BUILD_GUI,
null
)
}
if (event.code === 'KeyP') {
GameLib.Event.Emit(GameLib.Event.GAME_PAUSE);
}
};
GameLib.System.Input.prototype.onKeyUp = function(event) {
GameLib.Event.Emit(
GameLib.Event.KEY_UP,
{
code : event.code
}
);
if (event.code === 'ControlLeft') {
this.controlLeft = false;
}
};
GameLib.System.Input.prototype.onMouseDown = function(event) {
// console.log('mouse down');
GameLib.Event.Emit(
GameLib.Event.MOUSE_DOWN,
{
event : event
}
)
};
GameLib.System.Input.prototype.onMouseMove = function(event) {
// console.log('mouse move');
GameLib.Event.Emit(
GameLib.Event.MOUSE_MOVE,
{
event : event
}
)
};
GameLib.System.Input.prototype.onMouseWheel = function(event) {
// console.log('mouse wheel');
GameLib.Event.Emit(
GameLib.Event.MOUSE_WHEEL,
{
event : event
}
)
};
GameLib.System.Input.prototype.onMouseUp = function(event) {
// console.log('mouse up');
GameLib.Event.Emit(
GameLib.Event.MOUSE_UP,
{
event : event
}
)
};
GameLib.System.Input.prototype.onMouseDownEdit = function(event) {
if (event.button === 2) {
this.editorControls.map(
function(editorControl) {
if (this.controlLeft) {
return;
}
this.mouse.x = (event.offsetX / event.target.width ) * 2 - 1;
this.mouse.y = -(event.offsetY / event.target.height) * 2 + 1;
var scenes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Scene);
var intersects = scenes.reduce(
function (result, scene) {
editorControl.raycaster.instance.setFromCamera(
this.mouse,
editorControl.camera.instance
);
intersects = editorControl.raycaster.getIntersectedObjects(scene.meshes);
intersects.map(function (intersect) {
result.push(intersect);
});
return result;
}.bind(this),
[]
);
intersects.sort(
function (a, b) {
if (a.distance < b.distance) {
return -1;
}
if (a.distance > b.distance) {
return 1;
}
return 0;
}
);
var meshes = intersects.map(function (intersect) {
return intersect.mesh;
});
var mesh = meshes[0];
if (mesh) {
/**
* Prevent default action (like context menu or whatever)
*/
event.preventDefault();
/**
* Prevent other event listeners for 'mousedown' from executing their actions
*/
event.stopImmediatePropagation();
if (mesh.selected) {
this.deSelectMesh(mesh);
} else {
this.selectMesh(mesh);
}
/**
* Notify our GUI system to build a GUI
*/
GameLib.Event.Emit(
GameLib.Event.BUILD_GUI,
null
)
}
}.bind(this)
);
}
};
/**
*
* @param event
*/
GameLib.System.Input.prototype.onMouseMoveEdit = function(event) {
};
/**
* Update the camera position etc. after mouse up
* @returns {Function}
* @param event
*/
GameLib.System.Input.prototype.onMouseUpEdit = function(event) {
this.editorControls.map(
function(editorControl) {
editorControl.camera.position.x = editorControl.camera.instance.position.x;
editorControl.camera.position.y = editorControl.camera.instance.position.y;
editorControl.camera.position.z = editorControl.camera.instance.position.z;
editorControl.camera.quaternion.x = editorControl.camera.instance.quaternion.x;
editorControl.camera.quaternion.y = editorControl.camera.instance.quaternion.y;
editorControl.camera.quaternion.z = editorControl.camera.instance.quaternion.z;
editorControl.camera.quaternion.w = editorControl.camera.instance.quaternion.w;
editorControl.camera.lookAt.x = editorControl.instance.center.x;
editorControl.camera.lookAt.y = editorControl.instance.center.y;
editorControl.camera.lookAt.z = editorControl.instance.center.z;
editorControl.camera.lookAt.instance.copy(editorControl.instance.center);
}
);
};
/**
* Update our camera position after moving the mouse wheel
* @returns {Function}
* @param event
*/
GameLib.System.Input.prototype.onMouseWheelEdit = function(event) {
this.editorControls.map(
function(editorControl) {
editorControl.camera.position.x = editorControl.camera.instance.position.x;
editorControl.camera.position.y = editorControl.camera.instance.position.y;
editorControl.camera.position.z = editorControl.camera.instance.position.z;
}
);
};
GameLib.System.Input.prototype.selectMesh = function(mesh) {
/**
* If mesh is already selected, do nothing
*/
if (mesh.selected === true) {
return;
}
/**
* Notify our component as being 'selected'
* @type {boolean}
*/
mesh.selected = true;
mesh.createHelper();
GameLib.Event.Emit(
GameLib.Event.MESH_SELECTED,
{
mesh : mesh
}
);
};
GameLib.System.Input.prototype.deSelectMesh = function(mesh) {
mesh.selected = false;
mesh.removeHelper();
GameLib.Event.Emit(
GameLib.Event.MESH_DESELECTED,
{
mesh : mesh
}
);
};
//
// console.log('keypressed ' + event.code);
//
// if (event.code === 'KeyV') {
// //todo - change view
// }
//
//
// if (event.code == 'KeyG') {
// if (!this.meshMoveMode) {
// console.log('move mode');
// this.meshMoveMode = true;
// }
// }
//
// if (event.code == 'KeyX') {
// if (this.meshMoveMode) {
// console.log('move along x');
// this.meshMoveXMode = true;
// this.meshMoveYMode = false;
// this.meshMoveZMode = false;
// }
// }
//
// if (event.code == 'KeyY') {
// if (this.meshMoveMode) {
// console.log('move along y');
// this.meshMoveXMode = false;
// this.meshMoveYMode = true;
// this.meshMoveZMode = false;
// }
// }
//
// if (event.code == 'KeyZ') {
// if (this.meshMoveMode) {
// console.log('move along z');
// this.meshMoveXMode = false;
// this.meshMoveYMode = false;
// this.meshMoveZMode = true;
// }
// }
//
// if (event.code == 'Escape') {
// if (this.meshMoveMode) {
// this.meshMoveMode = false;
// console.log('TODO: implement restore positions');
// }
// }
//
// if (event.code == 'Enter') {
// if (this.meshMoveMode) {
// this.meshMoveMode = false;
// console.log('TODO: implement apply positions');
// }
// }
// };
// GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity) {
//
// return function(event) {
//
// if (event.button === 2) {
// event.cancelBubble = true;
//
// event.preventDefault();
//
// if (event.stopPropagation) {
// event.stopPropagation();
// }
//
// var meshes = entity.queryComponents(GameLib.D3.Mesh);
//
// var intersects = this.raycaster.getIntersectedObjects(meshes);
//
// if (intersects.length > 0) {
//
// console.log('object(s) instersected');
//
// // var index = -1;
// //
// // for (var s = 0; s < this.editor.selectedObjects.length; s++) {
// // if (this.editor.selectedObjects[s].object == intersects[0]) {
// // index = s;
// // break;
// // }
// // }
// //
// // if (index == -1) {
// // /**
// // * The object is not selected, select it
// // */
// // this.selectObject(intersects[0]);
// //
// // } else {
// // /**
// // * De-select the objec
// // */
// // var delta = Date.now() - this.editor.selectedObjects[index].lastUpdate;
// // if (delta > this.selectDelayMs) {
// // this.unselectObject(intersects[0]);
// // }
// // }
// //
// // if (this.editor.onSelectionChanged) {
// // this.editor.onSelectionChanged(this.editor);
// // }
// }
//
// return false;
// }
// }
// };
// /**
// * Mouse click events
// * @param event
// * @returns {boolean}
// */
// GameLib.D3.Input.Editor.prototype.onMouseDown = function(event) {
//
// if (event.button === 2) {
//
//
//
//
//
// }
//
// if (event.button == 0) {
// if (this.meshMoveMode) {
// this.meshMoveMode = false;
// this.meshMoveXMode = false;
// this.meshMoveYMode = false;
// this.meshMoveZMode = false;
// }
// }
// };
// /**
// * Mouse move events
// * @param event
// */
// GameLib.D3.Input.Editor.prototype.onMouseMove = function(event) {
//
// // var clientX = event.clientX - this.widthOffset;
// // this.mouse.x = ((clientX / (window.innerWidth - this.widthOffset))) * 2 - 1;
// // this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
//
// this.mouse.x = event.clientX;
// this.mouse.y = event.clientY;
//
// console.log("mouse (" + this.mouse.x + ", " + this.mouse.y + ")");
//
// this.raycaster.instance.setFromCamera(
// this.mouse,
// this.camera.instance
// );
//
// if (this.meshMoveMode) {
//
// var units = event.movementY;
//
// if (this.meshMoveXMode) {
// this.moveSelectedObjects('x', units);
// }
//
// if (this.meshMoveYMode) {
// this.moveSelectedObjects('y', units);
// }
//
// if (this.meshMoveZMode) {
// this.moveSelectedObjects('z', units);
// }
// }
// };
// /**
// * Moves selected objects along an axis
// * @param alongAxis
// * @param units
// */
// GameLib.D3.Input.Editor.prototype.moveSelectedObjects = function(alongAxis, units) {
//
// for (var s = 0; s < this.editor.selectedObjects.length; s++) {
//
// var object = this.editor.selectedObjects[s].object;
//
// if (object.position) {
// if (alongAxis == 'x') {
// object.position.x += units;
// }
// if (alongAxis == 'y') {
// object.position.y += units;
// }
// if (alongAxis == 'z') {
// object.position.z += units;
// }
//
// if (object.updateInstance) {
// object.updateInstance();
// }
// }
// }
// };
/**
* Linking System takes care of linking components and dependencies (after they have loaded) -
* and managing the relationships between objects - ex. what happens when a parent entity changes,
* or a parent scene changes.
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.Linking = function(
apiSystem
) {
GameLib.System.call(
this,
apiSystem
);
/**
* The dependencies of each component is tracked through this dependencies object -
* it maps the id of the object on which a component depends back to the component which depends on it,
* ex. texture.image = 'abcdefghi', then this.dependencies = {'abcdefghi' : [texture]}
* @type {{}}
*/
this.dependencies = {};
this.resolved = [];
/**
* Components
*/
this.componentCreatedSubscription = null;
this.componentClonedSubscription = null;
this.registerDependenciesSubscription = null;
this.componentRemoveSubscription = null;
/**
* Parents
*/
this.parentSceneChangeSubscription = null;
this.parentWorldChangeSubscription = null;
this.parentEntityChangeSubscription = null;
/**
* Instances
*/
this.instanceCreatedSubscription = null;
this.instanceClonedSubscription = null;
/**
* Meshes
*/
this.removeMeshSubscription = null;
/**
* Images
*/
this.imageChangedSubscription = null;
/**
* Materials
*/
this.materialTypeChangedSubscription = null;
/**
* Arrays
*/
this.arrayItemAddedSubscription = null;
};
GameLib.System.Linking.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Linking.prototype.constructor = GameLib.System.Linking;
GameLib.System.Linking.prototype.start = function() {
GameLib.System.prototype.start.call(this);
/**
* Components
*/
this.componentCreatedSubscription = this.subscribe(
GameLib.Event.COMPONENT_CREATED,
this.componentCreated.bind(this)
);
this.componentClonedSubscription = this.subscribe(
GameLib.Event.COMPONENT_CLONED,
this.componentCloned.bind(this)
);
this.registerDependenciesSubscription = this.subscribe(
GameLib.Event.REGISTER_DEPENDENCIES,
this.registerDependenciesDirect
);
this.componentRemoveSubscription = this.subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent
);
/**
* Parents
*/
this.parentSceneChangeSubscription = this.subscribe(
GameLib.Event.PARENT_SCENE_CHANGE,
this.onParentSceneChange
);
this.parentWorldChangeSubscription = this.subscribe(
GameLib.Event.PARENT_WORLD_CHANGE,
this.onParentWorldChange
);
this.parentEntityChangeSubscription = this.subscribe(
GameLib.Event.PARENT_ENTITY_CHANGE,
this.onParentEntityChange
);
/**
* Instances
*/
this.instanceCreatedSubscription = this.subscribe(
GameLib.Event.INSTANCE_CREATED,
this.instanceCreated
);
this.instanceClonedSubscription = this.subscribe(
GameLib.Event.INSTANCE_CLONED,
this.instanceCloned
);
/**
* Meshes
*/
this.removeMeshSubscription = this.subscribe(
GameLib.Event.REMOVE_MESH,
this.removeMesh
);
/**
* Images
*/
this.imageChangedSubscription = this.subscribe(
GameLib.Event.IMAGE_CHANGED,
this.imageChanged
);
/**
* Materials
*/
this.materialTypeChangedSubscription = this.subscribe(
GameLib.Event.MATERIAL_TYPE_CHANGED,
this.materialTypeChanged
);
/**
* Arrays
*/
this.arrayItemAddedSubscription = this.subscribe(
GameLib.Event.ARRAY_ITEM_ADDED,
this.arrayItemAdded
);
};
GameLib.System.Linking.prototype.link = function(component, data) {
for (var property in component.linkedObjects) {
if (component.linkedObjects.hasOwnProperty(property)) {
if (component.linkedObjects[property] instanceof Array) {
var linked = [];
component[property] = component[property].map(function (entry) {
if (entry === data.component.id) {
linked.push({
parent : component,
property : property,
child : data.component
});
return data.component;
} else {
return entry;
}
});
linked.map(function(link) {
GameLib.Event.Emit(
GameLib.Event.COMPONENT_LINKED,
link
);
})
} else {
if (component[property] &&
component[property] === data.component.id) {
component[property] = data.component;
GameLib.Event.Emit(
GameLib.Event.COMPONENT_LINKED,
{
parent : component,
property : property,
child : data.component
}
);
}
}
}
}
};
GameLib.System.Linking.prototype.resolveDependencies = function(component) {
if (!component.loaded) {
/**
* This component has not fully loaded - we should resolve dependencies to it later
*/
return false;
}
/**
* Now find all the components which depend on this component
*/
var parentComponents = this.dependencies[component.id];
/**
* If we don't have any components which depend on this component, simply return
*/
if (GameLib.Utils.UndefinedOrNull(parentComponents)) {
/**
* We don't know about components which depend on this component - but it could still load.
* However, it is stored in the register and dependency list for later use
*/
return false;
}
/**
* Otherwise, process them all
*/
parentComponents.map(
function (parentComponent) {
/**
* Link the parent component to this component
*/
this.link(parentComponent, {component: component});
/**
* We record that we linked a child component to a parent component
*/
GameLib.Utils.PushUnique(this.resolved, component);
/**
* First check if the dependencies have already been met
*/
if (
GameLib.Utils.UndefinedOrNull(parentComponent.dependencies) ||
(
parentComponent.dependencies instanceof Array &&
parentComponent.dependencies.length === 0
)
) {
/**
* This means - a parent component instance could maybe have been delayed to be created
* because the component constructor or linking system did not know at time of 'createInstance'
* that it required another object to fully become active
*/
if (
!parentComponent.loaded ||
GameLib.Utils.UndefinedOrNull(parentComponent.instance)
) {
try {
parentComponent.performInstanceCreation();
} catch (error) {
console.error(error);
}
} else {
/**
* These dependencies have already been met - the parentComponent properties have changed.
* It is time to 'update' this instance with this information (if any of it is relevant - depends
* on the component)
*/
// parentComponent.updateInstance();
}
} else {
/**
* Remove the actual dependency
*/
var index = parentComponent.dependencies.indexOf(component.id);
if (index !== -1) {
parentComponent.dependencies.splice(index, 1);
}
/**
* If we now managed to link the objects, and this object has no more dependencies
*/
if (parentComponent.dependencies.length === 0) {
parentComponent.performInstanceCreation();
}
}
}.bind(this)
);
/**
* We now linked all the components which depends on this component, to this component. Time to cleanup our
* dependencies
*/
delete this.dependencies[component.id];
/**
* For now this essentially only notifies the Editor - We have some more work to do however
*/
GameLib.Event.Emit(
GameLib.Event.UNRESOLVED_DEPENDENCIES_UPDATE,
{
dependencies : this.dependencies
}
);
/**
* If we happen to have no more dependencies - we linked a bunch of components which are ready to use
*/
if (GameLib.Utils.IsEmpty(this.dependencies)) {
/**
* This also only notifies the Editor - We still have some more work to here
*/
GameLib.Event.Emit(
GameLib.Event.COMPONENTS_LINKED,
{
components: this.resolved.map(
function(component) {
return component;
}
)
}
);
this.resolved = [];
}
//else {
// var keys = Object.keys(this.dependencies);
/**
* And this is it - we need to check if the dependencies array contains any 'resolved' components -
* If it does - resolve the dependencies of this newly 'resolved' component
*/
// this.resolved = this.resolved.reduce(
//
// function(result, component) {
//
// if (keys.indexOf(component.id) !== -1) {
// /**
// * We found a resolved component - which is a dependency for another component.
// * Resolve the dependencies of this component - this is recursive and should be done carefully
// */
// this.resolveDependencies(component);
// } else {
// result.push(component);
// }
//
// return result;
//
// }.bind(this),
// []
// );
//}
};
GameLib.System.Linking.prototype.registerDependencies = function(component) {
/**
* We only care about components with unloaded dependencies -
* other components will have already had their instance objects created
*/
if (component.dependencies &&
component.dependencies.length > 0) {
component.dependencies = component.dependencies.reduce(
function(result, id) {
/**
* Check if we already processed a component on which this component is dependent
*/
var processedComponent = GameLib.EntityManager.Instance.findComponentById(id);
if (processedComponent && processedComponent.loaded) {
/**
* Link the component
*/
this.link(component, {component: processedComponent});
GameLib.Utils.PushUnique(this.resolved, processedComponent);
} else {
/**
* Create a new link if none exists
*/
if (GameLib.Utils.UndefinedOrNull(this.dependencies[id])) {
this.dependencies[id] = [];
}
/**
* Don't store duplicate dependencies
*/
if (this.dependencies[id].indexOf(component) === -1) {
this.dependencies[id].push(component);
GameLib.Event.Emit(
GameLib.Event.UNRESOLVED_DEPENDENCIES_UPDATE,
{
dependencies : this.dependencies
}
);
}
/**
* Also - we remember that this component has a dependency
*/
result.push(id);
}
return result;
}.bind(this),
[]
);
if (component.dependencies.length === 0) {
component.performInstanceCreation();
}
}
};
/**
* When a component is created, register its dependencies, and try to resolve them
* @param data
*/
GameLib.System.Linking.prototype.componentCreated = function(data) {
/**
* Shorthand
*/
var component = data.component;
/**
* Register any dependencies of this component
*/
this.registerDependencies(component);
/**
* Resolve any dependencies to this component
*/
this.resolveDependencies(component);
};
GameLib.System.Linking.prototype.componentCloned = function(data) {
this.componentCreated(data);
if (data.component instanceof GameLib.D3.Mesh) {
if (!(data.parent instanceof GameLib.D3.Mesh)){
throw new Error('no scene parent');
}
if (data.parent.parentScene) {
data.parent.parentScene.addClone(data.component);
}
}
};
/**
* When you want to register dependencies directly - Component constructor does this when it knows the
* component instance cannot be created because it has a bunch of dependencies. So it tells the linking
* system about it, so the linking system can create the instance when the dependency loads or already exists
* @param data
*/
GameLib.System.Linking.prototype.registerDependenciesDirect = function(data) {
this.registerDependencies(data.component);
};
GameLib.System.Linking.prototype.removeComponent = function(data) {
if (!data.component) {
console.error('no component to remove');
return;
}
var component = data.component;
if (component.parentEntity instanceof GameLib.Entity) {
component.parentEntity.removeComponent(component);
}
if (component instanceof GameLib.D3.Mesh &&
component.parentScene instanceof GameLib.D3.Scene) {
component.removeHelper();
component.parentScene.removeObject(component);
}
if (component instanceof GameLib.D3.Light &&
component.parentScene instanceof GameLib.D3.Scene) {
component.parentScene.removeObject(component);
}
if (component instanceof GameLib.Entity) {
GameLib.EntityManager.Instance.removeEntity(component);
}
// if (component instanceof GameLib.D3.Particle) {
// // component.mesh.parentScene.removeObject(component.mesh);
// }
};
GameLib.System.Linking.prototype.imageChanged = function(data) {
var materials = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Material);
materials.map(function(material){
var textures = material.getTextures();
if (textures.indexOf(data.texture) !== -1) {
material.updateInstance();
}
});
};
GameLib.System.Linking.prototype.arrayItemAdded = function(data) {
if (
data.component instanceof GameLib.D3.PhysicsWorld &&
data.item instanceof GameLib.D3.RigidBody
) {
data.component.addRigidBody(data.item);
}
if (data.component instanceof GameLib.D3.Mesh &&
data.item instanceof GameLib.D3.Material
) {
data.component.addMaterial(data.item);
}
};
GameLib.System.Linking.prototype.instanceCloned = function(data) {
// if (data.component instanceof GameLib.D3.Particle) {
//
// var mesh = data.component.mesh;
//
// if (mesh.parentScene && mesh.parentScene.instance) {
// data.instance.userData.scene = mesh.parentScene.instance;
// mesh.parentScene.instance.add(data.instance);
// }
// }
};
GameLib.System.Linking.prototype.instanceCreated = function(data) {
this.resolveDependencies(data.component);
if (data.component instanceof GameLib.D3.Image) {
/**
* Find all textures which use this image
*/
GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Texture).map(
function(texture) {
if (texture.image === data.component ||
texture.images.indexOf(data.component) !== -1
) {
/**
* Ok - this image is in use - this should notify materials when its image changes
*/
texture.updateInstance('image');
}
}
);
}
/**
* Link all scenes
*/
if (data.component instanceof GameLib.D3.Scene) {
/**
* Check ALL components for 'parentScenes' - this is expensive so it checks the register directly
*/
GameLib.EntityManager.Instance.register.map(
function(component) {
if (component.parentScene === data.component.id) {
component.parentScene = data.component;
}
}
);
}
if (
data.component.parentScene &&
typeof data.component.parentScene === 'string'
) {
GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Scene).map(
function (scene) {
if (data.component.parentScene === scene.id) {
data.component.parentScene = scene;
scene.addObject(data.component);
}
}
);
}
if (
data.component.parentEngine &&
typeof data.component.parentEngine === 'string'
) {
GameLib.EntityManager.Instance.queryComponents(GameLib.D3.ParticleEngine).map(
function (particleEngine) {
if (data.component.parentEngine === particleEngine.id) {
data.component.parentEngine = particleEngine;
}
}
);
}
/**
* Link all meshes
*/
if (data.component instanceof GameLib.D3.Mesh) {
/**
* Check if this mesh is a parentMesh to any component- this is an expensive call, so check if we should call it
* Also - it inspects the register directly instead of querying it twice (since it checks ALL components)
*/
if (!data.preventParentMeshCheck) {
GameLib.EntityManager.Instance.register.map(
function (component) {
if (component.parentMesh &&
component.parentMesh === data.component.id ) {
component.parentMesh = data.component;
/**
* Check if a component has this mesh as a parent
*/
if (component instanceof GameLib.D3.Mesh) {
component.setParentMesh(data.component);
}
}
}
);
}
}
/**
* Maybe this component has a parent mesh
*/
if (
data.component.parentMesh &&
typeof data.component.parentMesh === 'string'
) {
GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh).map(
function (mesh) {
if (data.component.parentMesh === mesh.id) {
data.component.parentMesh = mesh;
if (data.component instanceof GameLib.D3.Mesh) {
data.component.setParentMesh(mesh);
}
}
}
);
}
if (
data.component.parentWorld &&
typeof data.component.parentWorld === 'string'
) {
GameLib.EntityManager.Instance.queryComponents(GameLib.D3.PhysicsWorld).map(
function (world) {
if (data.component.parentWorld === world.id) {
data.component.parentWorld = world;
if (typeof data.component.instance.addToWorld === 'function') {
data.component.instance.addToWorld(world.instance);
console.log('instance added to physics world');
}
}
}
);
}
};
GameLib.System.Linking.prototype.materialTypeChanged = function(data) {
var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh);
meshes.map(
function(mesh){
var inUse = mesh.materials.reduce(
function(result, material) {
if (material === data.material) {
result = true;
}
return result;
},
false
);
if (inUse) {
if (mesh.materials.length === 1) {
mesh.instance.material = mesh.materials[0].instance
} else {
mesh.instance.material = mesh.materials.map(
function(material) {
return material.instance;
}
)
}
mesh.instance.geometry.uvsNeedUpdate = true;
mesh.instance.material.needsUpdate = true;
}
}
);
};
/**
*
* @param data
*/
GameLib.System.Linking.prototype.onParentWorldChange = function(data) {
if (
data.object instanceof GameLib.D3.RigidBody
) {
if (data.originalWorld instanceof GameLib.D3.PhysicsWorld) {
data.originalWorld.removeRigidBody(data.object);
}
if (data.newWorld instanceof GameLib.D3.PhysicsWorld) {
data.newWorld.addRigidBody(data.object);
}
}
};
/**
* Defines what should happen when a parent scene changes
* @param data
*/
GameLib.System.Linking.prototype.onParentSceneChange = function(data) {
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
*/
var helper = GameLib.EntityManager.Instance.findHelperByObject(data.object);
if (helper) {
if (data.originalScene && data.originalScene.instance) {
data.originalScene.instance.remove(helper.instance);
}
data.newScene.instance.add(helper.instance);
}
/**
* We remove the mesh from the old scene and add it to the new scene
*/
if (data.originalScene && data.originalScene.removeObject) {
data.originalScene.removeObject(data.object);
}
if (data.newScene) {
data.newScene.addObject(data.object);
}
}
};
/**
* Change parent entity
* @param data
*/
GameLib.System.Linking.prototype.onParentEntityChange = function(data) {
if (data.originalEntity instanceof GameLib.Entity) {
data.originalEntity.removeComponent(data.object);
}
if (data.newEntity instanceof GameLib.Entity) {
data.newEntity.addComponent(data.object);
}
GameLib.Event.Emit(
GameLib.Event.PARENT_ENTITY_CHANGED,
{
originalEntity : data.originalEntity,
newEntity : data.newEntity,
component : data.object
}
)
};
/**
* When a mesh is deleted - build a list of all the mesh children objects - also - find out if any of these
* children objects are in use by another object - if it is - don't delete it, otherwise, do
* @param data
*/
GameLib.System.Linking.prototype.removeMesh = function(data) {
/**
* First we get the list of all components we would like to delete
*/
var componentsToDelete = data.meshes.reduce(
function(result, mesh) {
result.push(mesh);
var components = mesh.getChildrenComponents();
components.map(function(component){
result.push(component);
});
return result;
},
[]
);
/**
* Now, we want to get a list of all the meshes which we don't want to delete, and all their children
*/
var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh);
meshes = meshes.filter(function(mesh){
return data.meshes.indexOf(mesh) === -1;
});
/**
* Now we have a list of meshes still in use in meshes, now find all their children
*/
var componentsInUse = meshes.reduce(
function(result, mesh) {
result.push(mesh);
var components = mesh.getChildrenComponents();
components.map(function(component){
result.push(component);
});
return result;
},
[]
);
/**
* Now we don't want to remove any children in use, so filter out the components in use
*/
componentsToDelete = componentsToDelete.filter(
function(component) {
return componentsInUse.indexOf(component) === -1;
}
);
/**
* componentsToDelete should now be the final list of components to delete
*/
componentsToDelete.map(
function(component){
component.remove();
}
);
};
GameLib.System.Linking.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
/**
* Components
*/
this.componentCreatedSubscription.remove();
this.componentClonedSubscription.remove();
this.registerDependenciesSubscription.remove();
this.componentRemoveSubscription.remove();
/**
* Parents
*/
this.parentSceneChangeSubscription.remove();
this.parentWorldChangeSubscription.remove();
this.parentEntityChangeSubscription.remove();
/**
* Instances
*/
this.instanceCreatedSubscription.remove();
this.instanceClonedSubscription.remove();
/**
* Meshes
*/
this.removeMeshSubscription.remove();
/**
* Images
*/
this.imageChangedSubscription.remove();
/**
* Materials
*/
this.materialTypeChangedSubscription.remove();
/**
* Arrays
*/
this.arrayItemAddedSubscription.remove();
};
/**
* System takes care of updating all the entities (based on their component data)
* @param graphics
* @param camera
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.Particle = function(
graphics,
camera,
apiSystem
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
GameLib.System.call(
this,
apiSystem
);
/**
* this holds a reference to engine components and does some initial setup work so we don't have to do it during render
* like calculate frequency etc..
* @type {Array}
*/
this.engines = [];
this.camera = camera;
this.totalTime = 0;
this.instanceCreatedSubscription = null;
this.removeComponentSubscription = null;
this.beforeRenderSubscription = null;
};
GameLib.System.Particle.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Particle.prototype.constructor = GameLib.System.Particle;
/**
* Start this system (add all event listeners)
*/
GameLib.System.Particle.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.particleEngines = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.ParticleEngine);
this.instanceCreatedSubscription = GameLib.Event.Subscribe(
GameLib.Event.INSTANCE_CREATED,
this.instanceCreated.bind(this)
);
this.removeComponentSubscription = GameLib.Event.Subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent.bind(this)
);
this.beforeRenderSubscription = GameLib.Event.Subscribe(
GameLib.Event.BEFORE_RENDER,
this.beforeRender.bind(this)
);
};
/**
* From now on we want to track everything about a component, only from the systems that are active
* @param data
*/
GameLib.System.Particle.prototype.instanceCreated = function(data) {
if (data.component instanceof GameLib.D3.ParticleEngine) {
// console.log('new particle engine');
this.particleEngines.push(data.component);
}
if (data.component instanceof GameLib.D3.Camera) {
// console.log('new camera');
this.camera = data.component;
}
};
/**
* Removes a particle engine from this system
* @param data
*/
GameLib.System.Particle.prototype.removeComponent = function(data) {
if (data.component instanceof GameLib.D3.ParticleEngine) {
var index = this.particleEngines.indexOf(data.component);
if (index !== -1) {
// console.log('removing particle engine from system' + data.component.name);
this.particleEngines.splice(index, 1);
} else {
// console.log('failed to find the particle engine in the system : ' + data.component.name);
}
}
};
/**
* This is what actually happens to all particles before render
* @param data
*/
GameLib.System.Particle.prototype.beforeRender = function(data) {
this.totalTime += data.delta;
this.particleEngines.map(
function(particleEngine) {
if (
GameLib.Utils.UndefinedOrNull(particleEngine.camera) ||
GameLib.Utils.UndefinedOrNull(particleEngine.templateParticle) ||
GameLib.Utils.UndefinedOrNull(particleEngine.templateParticle.mesh) ||
GameLib.Utils.UndefinedOrNull(particleEngine.templateParticle.mesh.parentScene) ||
GameLib.Utils.UndefinedOrNull(particleEngine.templateParticle.mesh.parentScene.instance)) {
return;
}
particleEngine.elapsed += data.delta;
particleEngine.particles = particleEngine.particles.reduce(
function(result, particle){
var speed = particle.userData.speed;
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_CONSTANT) {
speed = data.delta * particle.userData.speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_LINEAR) {
speed = data.delta * particle.userData.speed;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_EXPONENTIAL) {
speed = Math.pow(particle.userData.speed, 2) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_LOGARITHMIC) {
speed = Math.log(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_LOG) {
speed = 1 / Math.log(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_EXP) {
speed = Math.exp(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_EXP) {
speed = 1 / Math.exp(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
particle.position.x += particle.userData.direction.x * speed;
particle.position.y += particle.userData.direction.y * speed;
particle.position.z += particle.userData.direction.z * speed;
if (particleEngine.templateParticle.scaleType === GameLib.D3.Particle.SCALE_TYPE_CONSTANT) {
/**
* Do nothing - scale should already be set
*/
/* particle.scale.x = particle.userData.scale.x;
particle.scale.y = particle.userData.scale.y;
particle.scale.z = particle.userData.scale.z;
*/
}
if (particleEngine.templateParticle.scaleType === GameLib.D3.Particle.SCALE_TYPE_LINEAR) {
particle.scale.x += particle.userData.scale.x * data.delta;
particle.scale.y += particle.userData.scale.x * data.delta;
particle.scale.z += particle.userData.scale.x * data.delta;
}
particle.quaternion.copy(particleEngine.camera.instance.quaternion);
if (particleEngine.templateParticle.opacityType === GameLib.D3.Particle.OPACITY_TYPE_INCREASE_LINEAR) {
particle.material.opacity += particleEngine.templateParticle.opacityFactor;
}
if (particleEngine.templateParticle.opacityType === GameLib.D3.Particle.OPACITY_TYPE_DECREASE_LINEAR) {
particle.material.opacity -= particleEngine.templateParticle.opacityFactor;
}
particle.userData.elapsed += data.delta;
if (
particle.userData.elapsed > particle.userData.lifeTime ||
particle.material.opacity < 0
) {
particle.userData.scene.remove(particle);
particle.geometry.dispose();
//particle.material.map.dispose();
particle.material.dispose();
} else {
result.push(particle);
}
return result;
},
[]
);
if (particleEngine.disabledForRemoval && particleEngine.particles.length === 0) {
GameLib.Event.Emit(
GameLib.Event.REMOVE_PARTICLE_ENGINE,
{
component : particleEngine
}
)
}
if (particleEngine.enabled && !particleEngine.disabledForRemoval) {
var instanceClone = null;
if (particleEngine.pulse) {
if (particleEngine.particles.length === 0) {
particleEngine.elapsed = 0;
/**
* This is a 'pulse' engine - so spawn all the particles at once and spawn again when all particles
* are gone
*/
for (var i = 0; i < particleEngine.particlesPerSecond; i++) {
instanceClone = particleEngine.templateParticle.cloneInstance();
particleEngine.particles.push(instanceClone);
}
}
} else {
/**
* This is a 'stream' engine - spawn particles one at a time when its time to do so
*/
if (particleEngine.elapsed > particleEngine.frequency) {
particleEngine.elapsed = 0;
instanceClone = particleEngine.templateParticle.cloneInstance();
particleEngine.particles.push(instanceClone);
}
}
}
}.bind(this)
)
};
/**
* Stop this system (remove all event listeners)
*/
GameLib.System.Particle.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.instanceCreatedSubscription.remove();
this.removeComponentSubscription.remove();
this.beforeRenderSubscription.remove();
};
/**
* System takes care of updating all the entities (based on their component data)
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.Physics = function(
apiSystem
) {
GameLib.System.call(
this,
apiSystem
);
this.worlds = [];
// this.rigidBodies = [];
// this.wheels = [];
// this.vehicles = [];
// this.worldSubscription = null;
// this.rigidBodySubscription = null;
this.beforeRenderSubscription = null;
this.afterRenderSubscription = null;
};
GameLib.System.Physics.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Physics.prototype.constructor = GameLib.System.Physics;
GameLib.System.Physics.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.worlds = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.PhysicsWorld);
// this.rigidBodies = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RigidBody);
// this.wheels = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RaycastWheel);
// this.vehicles = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.RaycastVehicle);
// this.worlds.map(
// function(world) {
// world.instance.addEventListener(
// 'postStep',
// function() {
//
// this.vehicles.map(
// function(vehicle) {
// vehicle.instance.wheelInfos.map(
// function(wheelInfo, index) {
// vehicle.instance.updateWheelTransform(index);
// var t = wheelInfo.worldTransform;
// // vehicle.wheels[index].instance.position.copy(t.position);
// // vehicle.wheels[index].instance.quaternion.copy(t.quaternion);
//
// // vehicle.raycastWheels[index].parentMesh.localPosition.x = t.position.x;
// // vehicle.raycastWheels[index].parentMesh.localPosition.y = t.position.y;
// // vehicle.raycastWheels[index].parentMesh.localPosition.z = t.position.z;
//
// // vehicle.raycastWheels[index].parentMesh.updateInstance();
// }
// );
// }
// );
//
//
// }.bind(this)
// )
// }.bind(this)
// );
this.beforeRenderSubscription = this.subscribe(
GameLib.Event.BEFORE_RENDER,
this.beforeRender
);
};
/**
* Update script
*/
GameLib.System.Physics.prototype.beforeRender = function(data) {
this.worlds.map(
function(world) {
if (world.instance) {
world.instance.step(data.delta);
world.rigidBodies.map(
function(rigidBody){
rigidBody.position.x = rigidBody.instance.position.x;
rigidBody.position.y = rigidBody.instance.position.y;
rigidBody.position.z = rigidBody.instance.position.z;
rigidBody.quaternion.x = rigidBody.instance.quaternion.x;
rigidBody.quaternion.y = rigidBody.instance.quaternion.y;
rigidBody.quaternion.z = rigidBody.instance.quaternion.z;
rigidBody.quaternion.w = rigidBody.instance.quaternion.w;
rigidBody.parentMesh.position.x = rigidBody.instance.position.x;
rigidBody.parentMesh.position.y = rigidBody.instance.position.y;
rigidBody.parentMesh.position.z = rigidBody.instance.position.z;
rigidBody.parentMesh.quaternion.x = rigidBody.instance.quaternion.x;
rigidBody.parentMesh.quaternion.y = rigidBody.instance.quaternion.y;
rigidBody.parentMesh.quaternion.z = rigidBody.instance.quaternion.z;
rigidBody.parentMesh.quaternion.w = rigidBody.instance.quaternion.w;
rigidBody.instance.getVelocityAtWorldPoint(new CANNON.Vec3(0,0,0), rigidBody.velocity.instance);
rigidBody.velocity.x = rigidBody.velocity.instance.x;
rigidBody.velocity.y = rigidBody.velocity.instance.y;
rigidBody.velocity.z = rigidBody.velocity.instance.z;
rigidBody.parentMesh.updateRotationFromAxisAngle = false;
rigidBody.parentMesh.updateInstance();
rigidBody.parentMesh.updateRotationFromAxisAngle = true;
}
)
}
}.bind(this)
);
};
GameLib.System.Physics.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.worlds = [];
this.rigidBodies = [];
this.wheels = [];
this.vehicles = [];
if (this.beforeRenderSubscription) {
this.beforeRenderSubscription.remove();
}
if (this.afterRenderSubscription) {
this.afterRenderSubscription.remove();
}
};
/**
* System takes care of updating all the entities (based on their component data)
* @param apiSystem GameLib.API.System
* @constructor
*/
GameLib.System.Render = function(
apiSystem
) {
GameLib.System.call(
this,
apiSystem
);
this.renderSubscription = null;
};
GameLib.System.Render.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Render.prototype.constructor = GameLib.System.Render;
/**
* Start the rendering system
*/
GameLib.System.Render.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.renderers = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Renderer);
this.statistics = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Stats);
this.instanceCreatedSubscription = GameLib.Event.Subscribe(
GameLib.Event.INSTANCE_CREATED,
this.instanceCreated.bind(this)
);
this.removeComponentSubscription = GameLib.Event.Subscribe(
GameLib.Event.REMOVE_COMPONENT,
this.removeComponent.bind(this)
);
this.renderSubscription = this.subscribe(
GameLib.Event.RENDER,
this.render
);
};
/**
* From now on we want to track everything about a component, only from the systems that are active
* @param data
*/
GameLib.System.Render.prototype.instanceCreated = function(data) {
if (data.component instanceof GameLib.D3.Renderer) {
console.log('new renderer');
this.renderers.push(data.component);
}
if (data.component instanceof GameLib.D3.Stats) {
console.log('new stats');
this.statistics.push(data.component);
}
};
/**
* Removes a particle engine from this system
* @param data
*/
GameLib.System.Render.prototype.removeComponent = function(data) {
if (data.component instanceof GameLib.D3.Renderer) {
var index = this.renderers.indexOf(data.component);
if (index !== -1) {
console.log('removing renderer from system');
this.renderers.splice(index, 1);
} else {
console.log('failed to find the renderer in the system : ' + data.component.name);
}
}
};
/**
* Render subscription script
*/
GameLib.System.Render.prototype.render = function(data) {
if (this.statistics) {
this.statistics.map(
function (statistics) {
statistics.start();
}
);
}
GameLib.Event.Emit(
GameLib.Event.BEFORE_RENDER,
data
);
if (this.renderers.length < 1) {
/**
* Do nothing
*/
} else if (this.renderers.length === 1) {
/**
* Quite simple - we have a renderer - it wants to render its stuff
*/
this.renderers[0].render(data.delta);
} else {
/**
* If we have multiple renderers, we have a problem - they don't share the same webGL context -
* So, we need to get their scenes and render them individually instead of trying to have both renderers render
* to the same canvas (sharing the same webgl context does not work)
*/
var scenes = this.renderers.reduce(
function(result, renderer) {
renderer.scenes.map(
function(scene){
result.push(scene);
}
);
return result;
},
[]
);
var renderer = GameLib.EntityManager.Instance.defaultRenderer;
if (GameLib.Utils.UndefinedOrNull(renderer)) {
/**
* No default renderer, using first one
*/
renderer = this.renderers[0];
}
renderer.render(data.delta, scenes);
}
GameLib.Event.Emit(
GameLib.Event.AFTER_RENDER,
data
);
if (this.statistics) {
this.statistics.map(
function (statistics) {
statistics.end();
}
);
}
};
/**
* Stop the rendering system
*/
GameLib.System.Render.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.instanceCreatedSubscription.remove();
this.removeComponentSubscription.remove();
this.renderSubscription.remove();
this.renderers.map(
function(renderer) {
if (renderer.statistics) {
renderer.statistics.resize();
renderer.domElement.instance.parentElement.removeChild(renderer.statistics.instance.dom);
}
}
);
this.renderers = [];
};
/**
* Storage System takes care loading and linking components and dependencies
* @param graphics
* @param apiSystem GameLib.API.System
* @param token
* @param apiUploadUrl
* @param onImageLoaded
* @param onImageProgress
* @param onImageError
* @param onComponentLoaded
* @param onComponentProgress
* @param onComponentError
* @constructor
*/
GameLib.System.Storage = function(
graphics,
apiSystem,
token,
apiUploadUrl,
onImageLoaded,
onImageProgress,
onImageError,
onComponentLoaded,
onComponentProgress,
onComponentError
) {
GameLib.System.call(
this,
apiSystem
);
if (GameLib.Utils.UndefinedOrNull(token)) {
token = null;
}
this.token = token;
if (GameLib.Utils.UndefinedOrNull(apiUploadUrl)) {
console.warn('Need an API Upload URL for a storage system');
apiUploadUrl = '';
}
this.apiUploadUrl = apiUploadUrl;
if (GameLib.Utils.UndefinedOrNull(onImageLoaded)) {
onImageLoaded = null;
}
this.onImageLoaded = onImageLoaded;
if (GameLib.Utils.UndefinedOrNull(onImageProgress)) {
onImageProgress = null;
}
this.onImageProgress = onImageProgress;
if (GameLib.Utils.UndefinedOrNull(onImageError)) {
onImageError = null;
}
this.onImageError = onImageError;
if (GameLib.Utils.UndefinedOrNull(onComponentLoaded)) {
onComponentLoaded = null;
}
this.onComponentLoaded = onComponentLoaded;
if (GameLib.Utils.UndefinedOrNull(onComponentProgress)) {
onComponentProgress = null;
}
this.onComponentProgress = onComponentProgress;
if (GameLib.Utils.UndefinedOrNull(onComponentError)) {
onComponentError = null;
}
this.onComponentError = onComponentError;
this.loaded = [];
this.loading = [];
this.failed = [];
this.otherDependencies = [];
this.loginSubscription = null;
this.saveSubscription = null;
this.loadSubscription = null;
this.loadImageSubscription = null;
this.blenderDataSubscription = null;
this.imageUploadCompleteSubscription = null;
this.fetchComponentTypesSubscription = null;
this.fetchComponentsSubscription = null;
};
GameLib.System.Storage.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Storage.prototype.constructor = GameLib.System.Storage;
GameLib.System.Storage.prototype.start = function() {
GameLib.System.prototype.start.call(this);
GameLib.Event.Emit(
GameLib.Event.GET_GRAPHICS_IMPLEMENTATION,
null,
function(graphics) {
this.graphics = graphics;
}.bind(this),
function() {
this.graphics = null;
}.bind(this)
);
GameLib.Event.Emit(
GameLib.Event.GET_PHYSICS_IMPLEMENTATION,
null,
function(physics) {
this.physics = physics;
}.bind(this),
function() {
this.physics = null;
}.bind(this)
);
GameLib.Event.Emit(
GameLib.Event.GET_CODER_IMPLEMENTATION,
null,
function(coder) {
this.coder = coder;
}.bind(this),
function() {
this.coder = null;
}.bind(this)
);
this.loginSubscription = this.subscribe(
GameLib.Event.LOGGED_IN,
function(data) {
this.token = data.token;
}
);
this.saveSubscription = this.subscribe(
GameLib.Event.SAVE_COMPONENT,
this.save
);
this.loadSubscription = this.subscribe(
GameLib.Event.LOAD_COMPONENT,
this.load
);
this.deleteSubscription = this.subscribe(
GameLib.Event.DELETE_COMPONENT,
this.delete
);
this.loadImageSubscription = this.subscribe(
GameLib.Event.LOAD_IMAGE,
this.loadImage
);
this.loadFontSubscription = this.subscribe(
GameLib.Event.LOAD_FONT,
this.loadFont
);
this.blenderDataSubscription = this.subscribe(
GameLib.Event.BLENDER_DATA_RECEIVED,
this.processBlenderData
);
this.imageUploadCompleteSubscription = this.subscribe(
GameLib.Event.IMAGE_UPLOAD_COMPLETE,
this.imageUploadComplete
);
this.fetchComponentTypesSubscription = this.subscribe(
GameLib.Event.FETCH_COMPONENT_TYPES,
this.fetchComponentTypes
);
this.fetchComponentsSubscription = this.subscribe(
GameLib.Event.FETCH_COMPONENTS,
this.fetchComponents
);
};
GameLib.System.Storage.prototype.delete = function(data) {
this.publish(
GameLib.Event.GET_API_URL,
null,
function(urlData) {
if (typeof XMLHttpRequest === 'undefined') {
console.log('Implement server side delete here');
return;
}
data.ids.map(function(id){
var xhr = new XMLHttpRequest();
xhr.open(
'POST',
urlData.apiUrl + '/component/delete/' + id
);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-authorization", urlData.passwoid);
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
try {
var response = JSON.parse(this.responseText)
} catch (error) {
GameLib.Event.Emit(
GameLib.Event.DELETE_COMPONENT_ERROR,
{
message: this.responseText
}
)
}
if (response.result === 'success') {
GameLib.Event.Emit(
GameLib.Event.COMPONENT_DELETED,
{
message: response.message || 'Successfully saved the component'
}
)
} else {
GameLib.Event.Emit(
GameLib.Event.DELETE_COMPONENT_ERROR,
{
message: response.message || 'The server responded but failed to save the component'
}
)
}
}
};
xhr.send(JSON.stringify({
session : this.token
}));
}.bind(this));
}.bind(this),
function(error) {
console.error(error.message);
throw new Error(error.message);
}
);
};
/**
* 'Saves' data to somewhere
*/
GameLib.System.Storage.prototype.save = function(data) {
var event = GameLib.Event.GET_API_URL;
if (data.remote) {
event = GameLib.Event.GET_REMOTE_API_URL
}
this.publish(
event,
null,
function(urlData) {
if (typeof XMLHttpRequest === 'undefined') {
console.log('Implement server side save here');
return;
}
var xhr = new XMLHttpRequest();
xhr.open(
'POST',
urlData.apiUrl + '/component/create'
);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-authorization", urlData.passwoid);
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
try {
var response = JSON.parse(this.responseText)
} catch (error) {
GameLib.Event.Emit(
GameLib.Event.SAVE_COMPONENT_ERROR,
{
message: this.responseText,
component : data.apiObject
}
)
}
if (response.result === 'success') {
GameLib.Event.Emit(
GameLib.Event.COMPONENT_SAVED,
{
message: response.message || 'Successfully saved the component',
component : data.apiObject
}
)
} else {
GameLib.Event.Emit(
GameLib.Event.SAVE_COMPONENT_ERROR,
{
message: response.message || 'The server responded but failed to save the component',
component : data.apiObject
}
)
}
}
};
xhr.send(JSON.stringify({
component : data.apiObject,
session : this.token
}));
}
);
};
GameLib.System.Storage.prototype.createRuntimeObject = function(responseText, clientErrorCallback) {
try {
var object = JSON.parse(responseText);
} catch (errorObject) {
if (this.onComponentError) {
this.onComponentError(errorObject);
}
if (clientErrorCallback) {
clientErrorCallback({
message : errorObject.message || 'JSON parse error'
})
}
GameLib.Event.Emit(
GameLib.Event.LOAD_COMPONENT_ERROR,
{error: errorObject}
);
return null;
}
if (object.result !== 'success') {
if (this.onComponentError) {
this.onComponentError(id, object);
}
if (clientErrorCallback) {
clientErrorCallback({
message : object.message || 'Server load error'
})
}
GameLib.Event.Emit(
GameLib.Event.LOAD_COMPONENT_ERROR,
{error : object}
);
return null;
}
var runtimeComponent = null;
/**
* Now we need to create the runtime component - this happens systematically.
* First, we create an API object from the Object, then a Runtime object from the API object
* Each component has a function 'FromObject' which essentially does this for you
*/
var component = object.component[0];
var componentName = GameLib.Component.GetComponentName(component.componentType);
var componentClass = eval(componentName);
var fn = componentClass['FromObject'];
if (component.componentType === GameLib.Component.COMPONENT_ENTITY) {
runtimeComponent = fn(component, GameLib.EntityManager.Instance);
} else {
try {
runtimeComponent = fn(component);
} catch (error) {
if (this.coder) {
try {
runtimeComponent = fn(this.coder, component);
} catch (error) {
}
}
if (!runtimeComponent && this.graphics) {
try {
runtimeComponent = fn(this.graphics, component);
} catch (error) {
}
}
if (!runtimeComponent && this.physics) {
try {
runtimeComponent = fn(this.physics, component);
} catch (error) {
/**
* ok - we don't cannot create this component
*/
}
}
}
if (!runtimeComponent) {
if (clientErrorCallback) {
clientErrorCallback({
result: 'failure',
message: 'Could not create a runtime component: ' + component.name
});
}
}
}
return runtimeComponent;
};
GameLib.System.Storage.prototype.loadComponent = function(apiUrl, toProcess, includeDependencies, clientCallback, clientErrorCallback) {
/**
* We just do an initial check if these components to process are already in the register -
* if so we remove them since we probably want to overwrite them with stale DB versions.
*
* We don't override runtime versions of the dependencies of the loading components - since they could be later.
* But we do override runtime versions of the loading component since the user actually selected them and clicked 'load'
*/
toProcess.map(
function(id) {
GameLib.Utils.PushUnique(this.loading, id);
var component = GameLib.EntityManager.Instance.findComponentById(id);
if (component) {
component.remove();
}
}.bind(this)
);
toProcess.map(
function(id) {
var xhr = new XMLHttpRequest();
xhr.onload = function(__system) {
return function () {
var runtimeComponent = __system.createRuntimeObject.bind(__system)(this.responseText);
if (!runtimeComponent) {
__system.failed.push(id);
return;
}
if (
runtimeComponent.parentEntity &&
typeof runtimeComponent.parentEntity === 'string'
) {
GameLib.EntityManager.Instance.queryComponents(GameLib.Entity).map(
function (entity) {
if (runtimeComponent.parentEntity === entity.id) {
runtimeComponent.parentEntity = entity;
}
}
);
}
GameLib.Event.Emit(
GameLib.Event.COMPONENT_CREATED,
{
component: runtimeComponent
}
);
__system.loaded.push(runtimeComponent.id);
if (includeDependencies) {
/**
* Before we announce the creation of this component, we should get
* a list of all dependencies of this component, because once we announce
* the creation of this component - the linking system will attempt to resolve
* all dependencies
*/
var dependencies = runtimeComponent.getDependencies();
__system.otherDependencies.map(
function(id) {
var index = dependencies.indexOf(id);
if (index !== -1) {
dependencies.splice(index, 1);
}
}
);
dependencies.map(
function(id) {
GameLib.Utils.PushUnique(this.otherDependencies, id);
}.bind(__system)
);
/**
* Don't try to download failed components again
*/
dependencies = dependencies.reduce(
function(result, id) {
if (__system.failed.indexOf(id) === -1) {
result.push(id);
} else {
console.log('ignoring failed component : ' + id);
}
return result;
}.bind(__system),
[]
);
/**
* Now - we should systematically check if we have the dependency already
* loaded (in our runtime environment) - if we have - we just ignore loading this dependency (for now)
*
* We don't override runtime versions of the same component in the database because the user
* could be working with it and it should be the latest version.
*/
dependencies = dependencies.reduce(
function (result, dependency) {
if (GameLib.EntityManager.Instance.findComponentById(dependency)) {
/**
* Don't add the dependency
*/
} else {
result.push(dependency);
}
return result;
},
[]
);
/**
* Also check if this dependency is not already in our loaded
*/
dependencies = dependencies.reduce(
function (result, dependency) {
if (__system.loaded.indexOf(dependency) === -1) {
result.push(dependency);
}
return result;
},
[]
);
/**
* We should now check our 'loading' list and add all dependencies which are not already in there
*/
dependencies.map(
function (dependency) {
GameLib.Utils.PushUnique(__system.loading, dependency);
}
);
__system.loadComponent(apiUrl, dependencies, includeDependencies, clientCallback, clientErrorCallback);
GameLib.Event.Emit(
GameLib.Event.LOAD_PROGRESS,
{
loaded : __system.loaded.length,
toProcess : dependencies.length
}
);
}
// GameLib.Event.Emit(
// GameLib.Event.COMPONENT_DOWNLOAD_COMPLETE,
// {
// loaded: __system.loaded
// }
// );
if (__system.onComponentLoaded) {
__system.onComponentLoaded(runtimeComponent);
}
}
}(this);
xhr.onprogress = function(__id) {
return function (progressEvent) {
var progress = 0;
if (progressEvent.total !== 0) {
progress = Math.round(Number(progressEvent.loaded / progressEvent.total) * 100);
}
if (this.onComponentProgress) {
this.onComponentProgress(__id, progress)
}
}.bind(this);
}(id);
xhr.onerror = function(__id) {
return function (error) {
console.warn('component load failed for component ID ' + __id);
if (this.onComponentError) {
this.onComponentError(__id, error)
}
if (clientErrorCallback) {
clientErrorCallback({
message : 'xhr request failure'
})
}
}.bind(this);
}(id);
xhr.open(
'GET',
apiUrl + '/component/load/' + id
);
xhr.send();
}.bind(this)
);
};
/**
* 'Loads' data from a url
*/
GameLib.System.Storage.prototype.load = function(data, clientCallback, clientErrorCallback) {
this.publish(
GameLib.Event.GET_API_URL,
null,
function(urlData) {
if (typeof XMLHttpRequest === 'undefined') {
console.log('Implement server side load here');
return;
}
if (data.ids && data.ids.length > 0) {
this.loadComponent(
urlData.apiUrl,
data.ids,
data.includeDependencies,
clientCallback,
clientErrorCallback
);
} else {
console.log('No components selected');
}
}.bind(this),
function(error) {
console.error(error.message);
throw new Error(error.message);
}
);
};
GameLib.System.Storage.prototype.xhrLoad = function(
url,
callback,
errorCallback
) {
if (typeof XMLHttpRequest === 'undefined') {
console.log('Implement server side load here');
return;
}
console.log("Loading...", 'success');
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (!xhr.responseText) {
console.log('Invalid response from server');
errorCallback({message : 'Invalid response from server'});
return;
}
try {
var response = JSON.parse(xhr.responseText);
} catch (error) {
error.message = 'Could not parse JSON';
errorCallback(error);
}
if (response.result !== 'success') {
return errorCallback({message : response.message || 'Unknown Error Occurred'});
}
callback(response);
}
};
xhr.onerror = errorCallback;
// TODO: authentication data append
// var object = {};
// object.session = this.session;
// var string = JSON.stringify(object);
// xhr.send(string);
xhr.send();
};
/**
* Fetches all component types from the provided API url
* @param data
* @param clientCallback
* @param clientErrorCallback
*/
GameLib.System.Storage.prototype.fetchComponentTypes = function(data, clientCallback, clientErrorCallback) {
this.xhrLoad(
data.url,
function(response) {
clientCallback({
ids : response.ids
})
},
clientErrorCallback
);
};
/**
* Fetches all components with the specified type from the provided API url
* @param data
* @param clientCallback
* @param clientErrorCallback
*/
GameLib.System.Storage.prototype.fetchComponents = function(data, clientCallback, clientErrorCallback) {
this.xhrLoad(
data.url,
function(response) {
clientCallback({
components : response.component
})
},
clientErrorCallback
);
};
/**
* Once we have an image uploaded - we should load them all again - if their runtime version already exist, do nothing,
* otherwise, create the runtime version of it
* @param data
*/
GameLib.System.Storage.prototype.imageUploadComplete = function(data) {
var runtimeImages = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Image);
/**
* Process all images - we have to load them in addition to creating their runtime components
*/
data.images.map(function(imageData){
var image = null;
if (imageData) {
/**
* Overrride this image if possible
* @type {GameLib.D3.Image}
*/
GameLib.D3.Image.FromObject(this.graphics, imageData);
} else {
image = runtimeImages.reduce(
function(result, runtimeImage){
if (imageData.id === runtimeImage.id) {
result = runtimeImage;
}
return result;
},
null
);
image.updateInstance();
}
}.bind(this));
};
/**
* Process Blender Data - Basically does what 'load' does - but because we already have the data we don't have
* a complicated load pattern - we create the runtime components in the best order we can (images load async unfortunately)
* and announce their creation so the linking system can link them
* @param data
*/
GameLib.System.Storage.prototype.processBlenderData = function(data) {
console.log('loading blender data');
/**
* Process all images - we have to load them in addition to creating their runtime components
*/
data.images.map(function(imageData){
var image = GameLib.D3.Image.FromObject(this.graphics, imageData);
GameLib.Event.Emit(
GameLib.Event.COMPONENT_CREATED,
{
component: image
}
);
}.bind(this));
/**
* Process all textures
*/
data.textures.map(function(textureData){
var texture = GameLib.D3.Texture.FromObject(this.graphics, textureData);
GameLib.Event.Emit(
GameLib.Event.COMPONENT_CREATED,
{
component: texture
}
);
}.bind(this));
/**
* Process all materials
*/
data.materials.map(function(materialData){
var material = GameLib.D3.Material.FromObject(this.graphics, materialData);
GameLib.Event.Emit(
GameLib.Event.COMPONENT_CREATED,
{
component: material
}
);
}.bind(this));
/**
* Now process all meshes
*/
data.meshes.map(function(meshData){
var mesh = GameLib.D3.Mesh.FromObject(this.graphics, meshData);
GameLib.Event.Emit(
GameLib.Event.COMPONENT_CREATED,
{
component: mesh
}
);
}.bind(this));
/**
* And that should be it...
*/
};
GameLib.System.Storage.prototype.loadFont = function(data, callback, errorCallback) {
console.log('loading font : ' + data.font.name);
this.publish(
GameLib.Event.GET_API_URL,
null,
function(urlData) {
var url = urlData.apiUrl + '/fonts/' + data.font.url + '?ts=' + Date.now();
var loader = new THREE.FontLoader();
loader.load(
url,
function ( font ) {
if (GameLib.Utils.IsEmpty(font.data)) {
errorCallback({message:'font is empty'});
} else {
callback(font);
}
}
);
}.bind(this),
function(error) {
errorCallback(error);
}
);
};
GameLib.System.Storage.prototype.loadImage = function(data) {
console.log('loading image : ' + data.image.name);
this.publish(
GameLib.Event.GET_API_URL,
null,
function(urlData) {
var onLoaded = this.onImageLoaded;
var onProgress = this.onImageProgress;
var onError = this.onImageError;
var image = data.image;
var url = urlData.apiUrl + image.path + image.fileName + image.extension + '?ts=' + Date.now();
var preflight = new XMLHttpRequest();
preflight.withCredentials = true;
preflight.open(
'OPTIONS',
url
);
preflight.setRequestHeader('Content-Type', 'application/json');
preflight.onload = function() {
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('GET', url);
xhr.setRequestHeader('Content-Type', image.contentType);
xhr.responseType = 'blob';
xhr.onload = function() {
var objectUrl = false;
var url = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoWEQMQBXD4hQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAABRSURBVGje7c8xDQAwCAAwmA3koA/PU8FB0jpo1nRc9uI4AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBgX0fjEoBa8xN1z4AAAAASUVORK5CYII=';
try {
if (this.response.type !== 'application/json') {
url = window.URL.createObjectURL(this.response);
objectUrl = true;
}
} catch (error) {
/**
* Do Nothing
*/
}
var img = document.createElement('img');
img.onload = function () {
if (objectUrl) {
window.URL.revokeObjectURL(url);
}
image.instance = img;
image.createInstance();
if (onLoaded) {
onLoaded(image, data.createTexture);
}
};
img.src = url;
};
xhr.onprogress = function(progressEvent) {
var progress = 0;
if (progressEvent.total !== 0) {
progress = Math.round(Number(progressEvent.loaded / progressEvent.total) * 100);
}
if (onProgress) {
onProgress(image, progress);
}
image.size = progressEvent.total;
};
xhr.onerror = function(error) {
console.warn('image load failed for image ' + image.name);
if (onError) {
onError(image, error)
}
};
xhr.send();
};
preflight.onerror = function(error) {
console.warn('image pre-flight request failed for image ' + image.name);
if (onError) {
onError(image, error);
}
};
preflight.send();
}.bind(this),
function(error) {
console.error(error.message);
throw new Error(error.message);
}
);
};
GameLib.System.Storage.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
this.loginSubscription.remove();
this.loadSubscription.remove();
this.saveSubscription.remove();
this.loadImageSubscription.remove();
this.loadFontSubscription.remove();
this.blenderDataSubscription.remove();
this.imageUploadCompleteSubscription.remove();
this.deleteSubscription.remove();
this.fetchComponentTypesSubscription.remove();
this.fetchComponentsSubscription.remove();
};
/**
* System takes care of updating all the entities (based on their component data)
* Visualization System takes care of visualizing all objects which are not meshes (like physics data)
*
* @param apiSystem GameLib.API.System
* @param graphics
* @param physics
* @constructor
*/
GameLib.System.Visualization = function(
apiSystem,
graphics,
physics
) {
GameLib.System.call(
this,
apiSystem
);
this.graphics = graphics;
this.graphics.isNotThreeThrow();
this.physics = physics;
this.physics.isNotCannonThrow();
this.visualizationSubscription = null;
this.stopVisualizationSubscription = null;
};
GameLib.System.Visualization.prototype = Object.create(GameLib.System.prototype);
GameLib.System.Visualization.prototype.constructor = GameLib.System.Visualization;
GameLib.System.Visualization.prototype.start = function() {
GameLib.System.prototype.start.call(this);
this.visualizationSubscription = this.subscribe(
GameLib.Event.VISUALIZE,
this.visualize
);
this.stopVisualizationSubscription = this.subscribe(
GameLib.Event.STOP_VISUALIZE,
this.stopVisualize
)
};
GameLib.System.Visualization.prototype.visualize = function(data) {
var shape = data.shape;
var parentMesh = shape.parentMesh;
shape.setFromMesh();
var apiMesh = new GameLib.D3.API.Mesh();
apiMesh.name = 'Visualization Mesh for Shape ' + shape.name;
if (shape instanceof GameLib.D3.Shape.HeightMap) {
var v0 = new CANNON.Vec3();
var v1 = new CANNON.Vec3();
var v2 = new CANNON.Vec3();
for (var xi = 0; xi < shape.heightData.length - 1; xi++) {
for (var yi = 0; yi < shape.heightData[xi].length - 1; yi++) {
for (var k = 0; k < 2; k++) {
shape.instance.getConvexTrianglePillar(xi, yi, k===0);
v0.copy(shape.instance.pillarConvex.vertices[0]);
v1.copy(shape.instance.pillarConvex.vertices[1]);
v2.copy(shape.instance.pillarConvex.vertices[2]);
v0.vadd(shape.instance.pillarOffset, v0);
v1.vadd(shape.instance.pillarOffset, v1);
v2.vadd(shape.instance.pillarOffset, v2);
apiMesh.vertices.push(
new GameLib.D3.API.Vertex(
new GameLib.API.Vector3(v0.x, v0.y, v0.z)
),
new GameLib.D3.API.Vertex(
new GameLib.API.Vector3(v1.x, v1.y, v1.z)
),
new GameLib.D3.API.Vertex(
new GameLib.API.Vector3(v2.x, v2.y, v2.z)
)
);
var i = apiMesh.vertices.length - 3;
apiMesh.faces.push(
new GameLib.D3.API.Face(
null,
null,
i,
i+1,
i+2
)
);
}
}
}
}
new GameLib.D3.Mesh(
this.graphics,
apiMesh
);
};
GameLib.System.Visualization.prototype.stopVisualize = function(data) {
};
GameLib.System.Visualization.prototype.stop = function() {
GameLib.System.prototype.stop.call(this);
if (this.visualizationSubscription) {
this.visualizationSubscription.remove();
}
if (this.stopVisualizationSubscription) {
this.stopVisualizationSubscription.remove();
}
};
/**
* Runtime vector2 for updating instance objects
* @param graphics GameLib.D3.Graphics
* @param parentObject GameLib.D3.*
* @param apiVector2 GameLib.API.Vector2
* @param grain Number
* @constructor
*/
GameLib.Vector2 = function (
graphics,
apiVector2,
parentObject,
grain
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiVector2)) {
apiVector2 = {};
apiVector2 = {};
}
if (apiVector2 instanceof GameLib.Vector2) {
return apiVector2;
}
GameLib.API.Vector2.call(
this,
apiVector2.x,
apiVector2.y
);
if (GameLib.Utils.UndefinedOrNull(parentObject)) {
parentObject = null;
}
this.parentObject = parentObject;
if (GameLib.Utils.UndefinedOrNull(grain)) {
grain = 0.001;
}
this.grain = grain;
this.createInstance();
};
GameLib.Vector2.prototype = Object.create(GameLib.API.Vector2.prototype);
GameLib.Vector2.prototype.constructor = GameLib.Vector2;
/**
* Creates an instance vector2
* @returns {*}
*/
GameLib.Vector2.prototype.createInstance = function() {
this.instance = new THREE.Vector2(this.x, this.y);
};
/**
* Updates the instance vector, calls updateInstance on the parent object
*/
GameLib.Vector2.prototype.updateInstance = function(property) {
this.instance.x = this.x;
this.instance.y = this.y;
if (this.parentObject &&
this.parentObject.updateInstance) {
this.parentObject.updateInstance(property);
}
};
/**
* Converts runtime vector to API Vector
* @returns {GameLib.API.Vector2}
*/
GameLib.Vector2.prototype.toApiObject = function() {
return new GameLib.API.Vector2(
this.x,
this.y
);
};
/**
* Copy
* TODO: Test
* @param v optional
* @returns {GameLib.Vector2}
*/
GameLib.Vector2.prototype.copy = function (v) {
if (GameLib.Utils.UndefinedOrNull(v)) {
return new GameLib.Vector2(
this.graphics,
new GameLib.API.Vector2(
this.x,
this.y
),
this.parentObject,
this.grain
);
} else {
this.x = v.x;
this.y = v.y;
return this;
}
};
/**
* Equals
* TODO: Test
* @param v
* @returns {boolean}
*/
GameLib.Vector2.prototype.equals = function(v) {
if ((this.x == v.x) &&
(this.y == v.y)) {
return true;
} else {
return false;
}
};
/**
* Add
* TODO: Test
* @param v
*/
GameLib.Vector2.prototype.add = function(v) {
if (
v instanceof GameLib.API.Vector2 ||
v instanceof GameLib.API.Vector3 ||
v instanceof GameLib.API.Vector4 ||
v instanceof GameLib.API.Quaternion
) {
this.x += v.x;
this.y += v.y;
} else {
console.warn('Could not add Vector2');
throw new Error('Could not add Vector2');
}
};
/**
* Subtract
* TODO: Test
* @param v
*/
GameLib.Vector2.prototype.subtract = function(v) {
if (
v instanceof GameLib.API.Vector2 ||
v instanceof GameLib.API.Vector3 ||
v instanceof GameLib.API.Vector4 ||
v instanceof GameLib.API.Quaternion
) {
this.x -= v.x;
this.y -= v.y;
} else {
console.warn('Could not subtract Vector2');
throw new Error('Could not subtract Vector2');
}
};
/**
* Multiply
* TODO: Test
* @param v
*/
GameLib.Vector2.prototype.multiply = function(v) {
if (
v instanceof GameLib.API.Vector2 ||
v instanceof GameLib.API.Vector3 ||
v instanceof GameLib.API.Vector4 ||
v instanceof GameLib.API.Quaternion
) {
this.x *= v.x;
this.y *= v.y;
} else if (typeof v == 'number') {
this.x *= v;
this.y *= v;
} else {
console.warn('Could not multiply Vector2');
throw new Error('Could not multiply Vector2');
}
};
/**
* Divide
* TODO: Test
* @param v
*/
GameLib.Vector2.prototype.divide = function(v) {
if (
v instanceof GameLib.API.Vector2 ||
v instanceof GameLib.API.Vector3 ||
v instanceof GameLib.API.Vector4 ||
v instanceof GameLib.API.Quaternion
) {
this.x *= (1.0 / v.x);
this.y *= (1.0 / v.y);
} else if (typeof v == 'number') {
this.x *= 1.0 / v;
this.y *= 1.0 / v;
} else {
console.warn('Could not divide Vector2');
throw new Error('Could not divide Vector2');
}
};
/**
* Clamp
* TODO: Test
* @param min GameLib.API.Vector2
* @param max GameLib.API.Vector2
* @returns {GameLib.Vector2}
*/
GameLib.Vector2.prototype.clamp = function(min, max) {
this.x = Math.max(min.x, Math.min(max.x, this.x));
this.y = Math.max(min.y, Math.min(max.y, this.y));
return this;
};
/**
* Length
* TODO: Test
* @returns {number}
*/
GameLib.Vector2.prototype.length = function() {
return Math.sqrt(
this.x * this.x + this.y * this.y
);
};
/**
* Dot product
* TODO: Test
* @param v
* @returns {number}
*/
GameLib.Vector2.prototype.dot = function(v) {
return this.x * v.x + this.y * v.y;
};
/**
* Normalize
* TODO: Test
*/
GameLib.Vector2.prototype.normalize = function() {
return this.multiply(1.0 / this.length());
};
/**
* TODO: Test
* Angle between this vector and origin
* @returns {number}
*/
GameLib.Vector2.prototype.angle = function() {
var angle = Math.atan2(this.y, this.x);
if ( angle < 0 ) angle += 2 * Math.PI;
return angle;
};
/**
* Interpolate to v from here
* TODO: Test
* @param v
* @param alpha
* @returns {GameLib.Vector2}
*/
GameLib.Vector2.prototype.lerp = function ( v, alpha ) {
return new GameLib.Vector2(
this.x + ( v.x - this.x ) * alpha,
this.y + ( v.y - this.y ) * alpha
);
};
/**
* Runtime apiVector3 for updating instance objects
* @param implementation GameLib.D3.Graphics
* @param apiVector3 GameLib.API.Vector3
* @param parentObject GameLib.*
* @param grain Number
* @constructor
*/
GameLib.Vector3 = function (
implementation,
apiVector3,
parentObject,
grain
) {
this.implementation = implementation;
if (implementation instanceof GameLib.D3.Graphics) {
this.physics = null;
this.graphics = implementation;
this.graphics.isNotThreeThrow();
} else if (implementation instanceof GameLib.D3.Physics) {
this.graphics = null;
this.physics = implementation;
this.physics.isNotCannonThrow();
} else {
throw new Error('Unhandled implementation : ' + implementation);
}
if (GameLib.Utils.UndefinedOrNull(apiVector3)) {
apiVector3 = {};
}
if (apiVector3 instanceof GameLib.Vector3) {
return apiVector3;
}
GameLib.API.Vector3.call(
this,
apiVector3.x,
apiVector3.y,
apiVector3.z
);
if (GameLib.Utils.UndefinedOrNull(parentObject)) {
parentObject = this;
}
this.parentObject = parentObject;
if (GameLib.Utils.UndefinedOrNull(grain)) {
grain = 0.001;
}
this.grain = grain;
this.createInstance();
};
GameLib.Vector3.prototype = Object.create(GameLib.API.Vector3.prototype);
GameLib.Vector3.prototype.constructor = GameLib.Vector3;
/**
* Creates an instance vector3
* @returns {*}
*/
GameLib.Vector3.prototype.createInstance = function() {
if (this.graphics) {
this.instance = new THREE.Vector3(
this.x,
this.y,
this.z
);
} else if (this.physics) {
this.instance = new CANNON.Vec3(
this.x,
this.y,
this.z
)
}
};
/**
* Updates the instance vector, calls updateInstance on the parent object
*/
GameLib.Vector3.prototype.updateInstance = function(property, preventParentUpdate) {
this.instance.x = this.x;
this.instance.y = this.y;
this.instance.z = this.z;
if (!preventParentUpdate &&
this.parentObject &&
this.parentObject !== this &&
this.parentObject.updateInstance) {
this.parentObject.updateInstance(property);
}
};
/**
* Converts runtime vector to API Vector
*/
GameLib.Vector3.prototype.toApiObject = function() {
return new GameLib.API.Vector3(
this.x,
this.y,
this.z
);
};
/**
* Creates a new copy of this Vector3
*/
GameLib.Vector3.prototype.copy = function() {
return new GameLib.Vector3(
this.implementation,
new GameLib.API.Vector3(
this.x,
this.y,
this.z
),
this.parentObject,
this.grain
)
};
GameLib.Vector3.prototype.clone = function() {
return new GameLib.Vector3(
this.implementation,
new GameLib.API.Vector3(
this.x,
this.y,
this.z
),
this.parentObject,
this.grain
)
};
/**
* Create a negative version of this vector
* @returns {GameLib.Vector3}
*/
GameLib.Vector3.prototype.negativeCopy = function() {
return new GameLib.Vector3(
this.implementation,
new GameLib.API.Vector3(
-this.x,
-this.y,
-this.z
),
this.parentObject,
this.grain
)
};
/**
* Applies rotation specified by axis / angle to this vector - its a wrapper for three..
* @param axis
* @param angle
*/
GameLib.Vector3.prototype.applyAxisAngle = function(axis, angle) {
this.instance.applyAxisAngle(
new THREE.Vector3(
axis.x,
axis.y,
axis.z
),
angle
);
this.x = this.instance.x;
this.y = this.instance.y;
this.z = this.instance.z;
};
GameLib.Vector3.prototype.setFrom = function(vector3) {
this.x = vector3.x;
this.y = vector3.y;
this.z = vector3.z;
};
/**
* Runtime apiVector4 for updating instance objects
* @param graphics GameLib.D3.Graphics
* @param apiVector4 GameLib.API.Vector4
* @param parentObject GameLib.*
* @param grain Number
* @constructor
*/
GameLib.Vector4 = function (
graphics,
apiVector4,
parentObject,
grain
) {
this.graphics = graphics;
this.graphics.isNotThreeThrow();
if (GameLib.Utils.UndefinedOrNull(apiVector4)) {
apiVector4 = {};
}
if (apiVector4 instanceof GameLib.Vector4) {
return apiVector4;
}
GameLib.API.Vector4.call(
this,
apiVector4.x,
apiVector4.y,
apiVector4.z,
apiVector4.w
);
if (GameLib.Utils.UndefinedOrNull(parentObject)) {
parentObject = null;
}
this.parentObject = parentObject;
if (GameLib.Utils.UndefinedOrNull(grain)) {
grain = 0.001;
}
this.grain = grain;
this.createInstance();
};
GameLib.Vector4.prototype = Object.create(GameLib.API.Vector4.prototype);
GameLib.Vector4.prototype.constructor = GameLib.Vector4;
/**
* Creates an instance vector4
* @returns {*}
*/
GameLib.Vector4.prototype.createInstance = function() {
this.instance = new THREE.Quaternion(
this.x,
this.y,
this.z,
this.w
);
};
/**
* Updates the instance vector, calls updateInstance on the parent object
*/
GameLib.Vector4.prototype.updateInstance = function(property) {
this.instance.x = this.x;
this.instance.y = this.y;
this.instance.z = this.z;
this.instance.w = this.w;
if (this.parentObject &&
this.parentObject.updateInstance) {
this.parentObject.updateInstance(property);
}
};
/**
* Converts runtime vector to API Vector
*/
GameLib.Vector4.prototype.toApiObject = function() {
return new GameLib.API.Vector4(
this.x,
this.y,
this.z,
this.w
);
};
GameLib.EntityManager.Instance = new GameLib.EntityManager();
if (typeof window !== 'undefined') {
window.GameLib = GameLib;
}
if (typeof module !== 'undefined') {
module.exports = GameLib;
}
//EXTENDING INTERFACES (Generated via gulp)
//END EXTENDING