diff --git a/src/r3-api-project.js b/src/r3-api-project.js new file mode 100644 index 0000000..6f9995f --- /dev/null +++ b/src/r3-api-project.js @@ -0,0 +1,108 @@ +/** + * API Project + * @param id + * @param name + * @param parentEntity + * @param users + * @param isPublic + * @param entities + * @param renderers + * @param cameras + * @param cameraIndex + * @param controls + * @param mode + * @constructor + */ +R3.API.Project = function( + id, + name, + parentEntity, + users, + isPublic, + entities, + renderers, + cameras, + cameraIndex, + controls, + mode +) { + if (R3.Utils.UndefinedOrNull(id)) { + id = R3.Utils.RandomId(); + } + this.id = id; + + if (R3.Utils.UndefinedOrNull(name)) { + name = 'Project (' + this.id + ')'; + } + this.name = name; + + if (R3.Utils.UndefinedOrNull(users)) { + throw new Error('Only registered users can create projects'); + } + this.users = users; + + if (R3.Utils.UndefinedOrNull(isPublic)) { + isPublic = true; + } + this.isPublic = isPublic; + + if (R3.Utils.UndefinedOrNull(entities)) { + entities = []; + } + this.entities = entities; + + if (R3.Utils.UndefinedOrNull(renderers)) { + renderers = [new R3.API.Renderer.D3()]; + } + this.renderers = renderers; + + if (R3.Utils.UndefinedOrNull(cameras)) { + var editCamera = new R3.D3.API.Camera.Perspective( + { + name : 'Edit Camera' + } + ); + var runCamera = new R3.D3.API.Camera.Perspective( + { + name : 'Run Camera' + } + ); + cameras = [editCamera, runCamera]; + } + this.cameras = cameras; + + if (R3.Utils.UndefinedOrNull(cameraIndex)) { + cameraIndex = R3.API.Project.CAMERA_INDEX_EDIT; + } + this.cameraIndex = cameraIndex; + + if (R3.Utils.UndefinedOrNull(controls)) { + controls = new R3.API.Controls.D3.Orbit( + { + canvas: this.renderer.canvas + }, + this.cameras[this.cameraIndex] + ) + } + this.controls = controls; + + if (R3.Utils.UndefinedOrNull(mode)) { + mode = R3.API.Project.DEFAULT_MODE_EDIT; + } + this.mode = mode; + + R3.API.Component.call( + this, + R3.Component.PROJECT, + parentEntity + ); +}; + +R3.API.Project.prototype = Object.create(R3.API.Component.prototype); +R3.API.Project.prototype.constructor = R3.API.Project; + +R3.API.Project.DEFAULT_MODE_RUN = 0x1; +R3.API.Project.DEFAULT_MODE_EDIT = 0x2; + +R3.API.Project.CAMERA_INDEX_EDIT = 0x0; +R3.API.Project.CAMERA_INDEX_RUN = 0x1; \ No newline at end of file diff --git a/src/r3-api-user.js b/src/r3-api-user.js new file mode 100644 index 0000000..93df188 --- /dev/null +++ b/src/r3-api-user.js @@ -0,0 +1,87 @@ +/** + * API User + * @param id + * @param name + * @param parentEntity + * @param googleId + * @param fullName + * @param givenName + * @param familyName + * @param imageUrl + * @param email + * @param uploadFolder + * @param idToken + * @constructor + */ +R3.API.User = function( + id, + name, + parentEntity, + googleId, + fullName, + givenName, + familyName, + imageUrl, + email, + uploadFolder, + idToken +) { + if (R3.Utils.UndefinedOrNull(id)) { + id = R3.Utils.RandomId(); + } + this.id = id; + + if (R3.Utils.UndefinedOrNull(name)) { + name = 'User (' + this.id + ')'; + } + this.name = name; + + if (R3.Utils.UndefinedOrNull(googleId)) { + throw new Error('invalid user - no google ID'); + } + this.googleId = googleId; + + if (R3.Utils.UndefinedOrNull(fullName)) { + fullName = 'unknown full name'; + } + this.fullName = fullName; + + if (R3.Utils.UndefinedOrNull(givenName)) { + givenName = 'unknown given name'; + } + this.givenName = givenName; + + if (R3.Utils.UndefinedOrNull(familyName)) { + familyName = 'unknown family name'; + } + this.familyName = familyName; + + if (R3.Utils.UndefinedOrNull(imageUrl)) { + imageUrl = 'unknown image URL'; + } + this.imageUrl = imageUrl; + + if (R3.Utils.UndefinedOrNull(email)) { + throw new Error('invalid user - no email address'); + } + this.email = email; + + if (R3.Utils.UndefinedOrNull(uploadFolder)) { + uploadFolder = email.replace('/','_DS_'); + } + this.uploadFolder = uploadFolder; + + if (R3.Utils.UndefinedOrNull(idToken)) { + idToken = 'unknown ID token'; + } + this.idToken = idToken; + + R3.API.Component.call( + this, + R3.Component.USER, + parentEntity + ); +}; + +R3.API.User.prototype = Object.create(R3.API.Component.prototype); +R3.API.User.prototype.constructor = R3.API.User; diff --git a/src/r3-d3-api-camera-perspective-stereo.js b/src/r3-d3-api-camera-perspective-stereo.js new file mode 100644 index 0000000..7dd19fe --- /dev/null +++ b/src/r3-d3-api-camera-perspective-stereo.js @@ -0,0 +1,45 @@ +/** + * R3.D3.API.Camera.Perspective.Stereo + * @constructor + * @param apiD3ObjectCameraPerspective + * @param stereoMode + */ +R3.D3.API.Camera.Perspective.Stereo = function( + apiD3ObjectCameraPerspective, + stereoMode +) { + + if (R3.Utils.UndefinedOrNull(apiD3ObjectCameraPerspective)) { + apiD3ObjectCameraPerspective = { + objectType : R3.D3.API.Object.OBJECT_TYPE_CAMERA_PERSPECTIVE_STEREO + }; + } + + if (R3.Utils.UndefinedOrNull(apiD3ObjectCameraPerspective.objectType)) { + apiD3ObjectCameraPerspective.objectType = R3.D3.API.Object.OBJECT_TYPE_CAMERA_PERSPECTIVE_STEREO; + } + + if (R3.Utils.UndefinedOrNull(stereoMode)) { + stereoMode = R3.D3.API.Camera.Perspective.Stereo.STEREO_MODE_STEREO; + } + this.stereoMode = stereoMode; + + R3.D3.API.Camera.Perspective.call( + this, + apiD3ObjectCameraPerspective, + apiD3ObjectCameraPerspective.near, + apiD3ObjectCameraPerspective.far, + apiD3ObjectCameraPerspective.fov, + apiD3ObjectCameraPerspective.filmGauge, + apiD3ObjectCameraPerspective.filmOffset, + apiD3ObjectCameraPerspective.focus, + apiD3ObjectCameraPerspective.zoom + ); +}; + +R3.D3.API.Camera.Perspective.Stereo.prototype = Object.create(R3.D3.API.Camera.Perspective.prototype); +R3.D3.API.Camera.Perspective.Stereo.prototype.constructor = R3.D3.API.Camera.Perspective.Stereo; + +R3.D3.API.Camera.Perspective.Stereo.STEREO_MODE_STEREO = 0x1; +R3.D3.API.Camera.Perspective.Stereo.STEREO_MODE_ANAGLYPH = 0x2; +R3.D3.API.Camera.Perspective.Stereo.STEREO_MODE_PARALLAX = 0x3; diff --git a/src/r3-d3-camera-perspective-stereo.js b/src/r3-d3-camera-perspective-stereo.js new file mode 100644 index 0000000..b7e8c49 --- /dev/null +++ b/src/r3-d3-camera-perspective-stereo.js @@ -0,0 +1,87 @@ +/** + * R3.D3.Camera.Perspective.Stereo + * @param graphics R3.GraphicsRuntime + * @param apiD3ObjectPerspectiveStereoCamera + * @constructor + */ +R3.D3.Camera.Perspective.Stereo = function( + graphics, + apiD3ObjectPerspectiveStereoCamera +) { + + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + if (R3.Utils.UndefinedOrNull(apiD3ObjectPerspectiveStereoCamera)) { + apiD3ObjectPerspectiveStereoCamera = { + objectType : R3.D3.API.Object.OBJECT_TYPE_CAMERA_PERSPECTIVE_STEREO + }; + } + + R3.D3.API.Camera.Perspective.Stereo.call( + this, + apiD3ObjectPerspectiveStereoCamera, + apiD3ObjectPerspectiveStereoCamera.stereoMode + ); + + R3.D3.Camera.call( + this, + this.graphics, + this + ); + +}; + +R3.D3.Camera.Perspective.Stereo.prototype = Object.create(R3.D3.Camera.Perspective.prototype); +R3.D3.Camera.Perspective.Stereo.prototype.constructor = R3.D3.Camera.Perspective.Stereo; + +/** + * Creates a camera instance + * @returns {*} + */ +R3.D3.Camera.Perspective.Stereo.prototype.createInstance = function() { + + this.instance = new THREE.PerspectiveCamera(); + + var instance = new THREE.StereoCamera(); + + for (var property in instance) { + if ( + instance.hasOwnProperty(property) || + typeof instance[property] === 'function' + ) { + this.instance[property] = instance[property]; + } + } + + R3.D3.Camera.prototype.createInstance.call(this); +}; + +/** + * Updates the instance with the current state + */ +R3.D3.Camera.Perspective.Stereo.prototype.updateInstance = function(property) { + + if (property === 'stereoMode') { + console.warn('todo: update stereo mode'); + return; + } + + R3.D3.Camera.prototype.updateInstance.call(this, property); +}; + +/** + * Converts a R3.D3.Camera to a R3.D3.API.Camera + * @returns {R3.D3.API.Camera} + */ +R3.D3.Camera.Perspective.Stereo.prototype.toApiObject = function() { + + var apiCamera = R3.D3.Camera.prototype.toApiObject.call(this); + + var apiStereoCamera = new R3.D3.API.Camera.Perspective.Stereo( + apiCamera, + this.stereoMode + ); + + return apiStereoCamera; +}; diff --git a/src/r3-project.js b/src/r3-project.js new file mode 100644 index 0000000..786be0d --- /dev/null +++ b/src/r3-project.js @@ -0,0 +1,230 @@ +/** + * R3.Project + * @param apiProject R3.API.Project + * @constructor + */ +R3.Project = function( + apiProject +) { + + if (R3.Utils.UndefinedOrNull(apiProject)) { + apiProject = {}; + } + + R3.API.Project.call( + this, + apiProject.id, + apiProject.name, + apiProject.parentEntity, + apiProject.users, + apiProject.isPublic, + apiProject.entities, + apiProject.renderers, + apiProject.cameras, + apiProject.cameraIndex, + apiProject.controls, + apiProject.mode + ); + + this.users = this.users.map( + function(apiUser) { + + if (typeof apiUser === 'string') { + return apiUser; + } + + return new R3.User( + apiUser + ); + + }.bind(this) + ); + + this.entities = this.entities.map( + function(apiEntity) { + + if (typeof apiEntity === 'string') { + return apiEntity; + } + + return new R3.Entity( + apiEntity + ); + + }.bind(this) + ); + + var graphics = null; + + R3.Event.Emit( + R3.Event.GET_RUNTIME, + function(runtime) { + graphics = runtime.graphics; + } + ); + + var renderers = []; + + this.renderers.map( + function (renderer) { + if ( + renderer instanceof R3.API.Renderer.D2 || + renderer instanceof R3.API.Renderer.D3 + ) { + /** + * We need to get the runtime + * @type {R3.Renderer.D2|R3.Renderer.D2|R3.Renderer.D2} + */ + if (graphics === null) { + throw new Error('You require a graphics runtime in order to create a renderer'); + } + + if (renderer instanceof R3.API.Renderer.D2) { + renderer = new R3.Renderer.D2(graphics, renderer) + } + + if (renderer instanceof R3.API.Renderer.D3) { + renderer = new R3.Renderer.D3(graphics, renderer) + } + } + + renderers.push(renderer); + } + ); + this.renderers = renderers; + + var cameras = []; + + this.cameras.map( + function(rawCamera) { + if (rawCamera instanceof R3.D3.API.Camera) { + + if (graphics === null) { + throw new Error('You require a graphics runtime in order to create a 3D camera'); + } + + cameras.push(R3.Component.ConstructFromObject(rawCamera)); + } + } + ); + + this.cameras = cameras; + + if (this.controls instanceof R3.API.Controls.D3) { + + if (graphics === null) { + throw new Error('You require a graphics runtime in order to create 3D Controls'); + } + + this.controls = R3.Component.ConstructFromObject(this.controls); + } + + R3.Component.call( + this, + { + 'users' : R3.User, + 'entities' : [R3.Entity], + 'renderer' : [R3.Renderer], + 'cameras' : [R3.D3.Camera], + 'controls' : R3.Controls.D3 + } + ); +}; + +R3.Project.prototype = Object.create(R3.Component.prototype); +R3.Project.prototype.constructor = R3.Project; + +R3.Project.prototype.createInstance = function() { + this.instance = true; + R3.Component.prototype.createInstance.call(this); +}; + +/** + * Updates the instance with the current state + */ +R3.Project.prototype.updateInstance = function(property) { + + if (property === 'name') { + console.log('todo: project name update'); + } + + if (property === 'users') { + console.log('todo: project users update'); + } + + if (property === 'isPublic') { + console.log('todo: project isPublic update'); + } + + if (property === 'entities') { + console.log('todo: project entities update'); + } + + if (property === 'renderer') { + console.log('todo: project renderer update'); + } + + if (property === 'cameras') { + console.log('todo: project cameras update'); + } + + if (property === 'cameraIndex') { + console.log('todo: project cameraIndex update'); + } + + if (property === 'controls') { + console.log('todo: project controls update'); + } + + if (property === 'mode') { + console.log('todo: project mode update'); + } + + R3.Component.prototype.updateInstance.call(this, property); +}; + +/** + * Converts a R3.Project to a new R3.API.Project + * @returns {R3.API.Project} + */ +R3.Project.prototype.toApiObject = function() { + + var apiUsers = this.users.map( + function(user) { + return R3.Utils.IdOrNull(user); + } + ); + + var apiEntities = this.users.map( + function(entity) { + return R3.Utils.IdOrNull(entity); + } + ); + + var apiRenderers = this.renderers.map( + function(renderer) { + return R3.Utils.IdOrNull(renderer); + } + ); + + var apiCameras = this.cameras.map( + function(camera) { + return R3.Utils.IdOrNull(camera); + } + ); + + return new R3.API.Project( + this.id, + this.name, + R3.Utils.IdOrNull(this.parentEntity), + apiUsers, + this.isPublic, + apiEntities, + apiRenderers, + apiCameras, + this.cameraIndex, + R3.Utils.IdOrNull(this.controls), + this.mode + ); + +}; diff --git a/src/r3-user.js b/src/r3-user.js new file mode 100644 index 0000000..72e34f5 --- /dev/null +++ b/src/r3-user.js @@ -0,0 +1,105 @@ +/** + * R3.User + * @param apiUser R3.API.User + * @constructor + */ +R3.User = function( + apiUser +) { + + if (R3.Utils.UndefinedOrNull(apiUser)) { + apiUser = {}; + } + + R3.API.User.call( + this, + apiUser.id, + apiUser.name, + apiUser.parentEntity, + apiUser.googleId, + apiUser.fullName, + apiUser.givenName, + apiUser.familyName, + apiUser.imageUrl, + apiUser.email, + apiUser.uploadFolder, + apiUser.idToken + ); + + R3.Component.call(this); +}; + +R3.User.prototype = Object.create(R3.Component.prototype); +R3.User.prototype.constructor = R3.User; + +R3.User.prototype.createInstance = function() { + this.instance = true; + R3.Component.prototype.createInstance.call(this); +}; + +/** + * Updates the instance with the current state + */ +R3.User.prototype.updateInstance = function(property) { + + if (property === 'name') { + console.log('todo: user name update'); + } + + if (property === 'googleId') { + console.log('todo: user googleId update'); + } + + if (property === 'fullName') { + console.log('todo: user fullName update'); + } + + if (property === 'givenName') { + console.log('todo: user givenName update'); + } + + if (property === 'familyName') { + console.log('todo: user familyName update'); + } + + if (property === 'imageUrl') { + console.log('todo: user imageUrl update'); + } + + if (property === 'email') { + console.log('todo: user email update'); + } + + if (property === 'uploadFolder') { + console.log('todo: user uploadFolder update'); + } + + if (property === 'idToken') { + console.log('todo: user idToken update'); + } + + R3.Component.prototype.updateInstance.call(this, property); +}; + +/** + * Converts a R3.User to a new R3.API.User + * @returns {R3.API.User} + */ +R3.User.prototype.toApiObject = function() { + + return new R3.API.User( + this.id, + this.name, + R3.Utils.IdOrNull(this.parentEntity), + this.googleId, + this.fullName, + this.givenName, + this.familyName, + this.imageUrl, + this.email, + this.uploadFolder, + this.idToken + + ); + +};