32508 lines
839 KiB
JavaScript
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
|