mirror of
https://github.com/sbrl/Nibriboard.git
synced 2018-01-10 21:33:49 +00:00
[client] Refactor OtherClient data into class.
This commit is contained in:
parent
3689f685b9
commit
74c7c64015
4 changed files with 381 additions and 8 deletions
|
@ -8,6 +8,7 @@ window.panzoom = require("pan-zoom");
|
|||
// Our files
|
||||
import RippleLink from './RippleLink';
|
||||
import ViewportSyncer from './ViewportSyncer';
|
||||
import OtherClient from './OtherClient';
|
||||
import { get } from './Utilities';
|
||||
|
||||
class BoardWindow extends EventEmitter
|
||||
|
@ -164,12 +165,11 @@ class BoardWindow extends EventEmitter
|
|||
{
|
||||
context.save();
|
||||
|
||||
for (let [clientId, clientData] of this.otherClients)
|
||||
for (let [otherClientId, otherClient] of this.otherClients)
|
||||
{
|
||||
// TODO: Filter rendering by working out if this client is actually inside our viewport or not here
|
||||
// TODO: Refactor the other client information out into another class.
|
||||
context.save();
|
||||
context.translate(clientData.AbsCursorPosition.X, clientData.AbsCursorPosition.Y);
|
||||
context.translate(otherClient.CursorPosition.x, otherClient.CursorPosition.y);
|
||||
|
||||
context.beginPath();
|
||||
// Horizontal line
|
||||
|
@ -179,7 +179,7 @@ class BoardWindow extends EventEmitter
|
|||
context.moveTo(0, -this.otherCursorRadius);
|
||||
context.lineTo(0, this.otherCursorRadius);
|
||||
|
||||
context.strokeStyle = clientData.Colour;
|
||||
context.strokeStyle = otherClient.Colour;
|
||||
context.lineWidth = this.otherCursorWidth
|
||||
context.stroke();
|
||||
|
||||
|
@ -225,16 +225,26 @@ class BoardWindow extends EventEmitter
|
|||
this.sidebar.style.borderTopColor = this.Colour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles peer update messages recieved from the server via the RippleLink.
|
||||
*/
|
||||
handlePeerUpdates(message) {
|
||||
// Update our knowledge about other clients
|
||||
for (let otherClient of message.ClientStates) {
|
||||
// If this client is new, emit an event about it
|
||||
if(!this.otherClients.has(otherClient.Id))
|
||||
if(!this.otherClients.has(otherClient.Id)) {
|
||||
this.emit("OtherClientConnect", otherClient);
|
||||
else // If not, emit a normal update message about it
|
||||
|
||||
// Convert the raw object into a class instance
|
||||
let otherClientObj = new OtherClient();
|
||||
otherClientObj.Id = otherClient.Id;
|
||||
}
|
||||
else { // If not, emit a normal update message about it
|
||||
this.emit("OtherClientUpdate", otherClient);
|
||||
// Store the information for later
|
||||
this.otherClients.set(otherClient.Id, otherClient);
|
||||
}
|
||||
|
||||
// Get the OtherClient instance to pull in the rest of the data
|
||||
this.otherClients.get(otherClient.Id).update(otherClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
37
Nibriboard/ClientFiles/OtherClient.js
Normal file
37
Nibriboard/ClientFiles/OtherClient.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
"use strict";
|
||||
|
||||
import Vector from './Utilities/Vector';
|
||||
import Rectangle from './Utilities/Rectangle';
|
||||
|
||||
class OtherClient
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
// The unique id of this client.
|
||||
this.Id = -1;
|
||||
// The name of this client.
|
||||
this.Name = "";
|
||||
// The colour the server assigned to this client.
|
||||
this.Colour = "green";
|
||||
// The position of this clients' cursor.
|
||||
this.CursorPosition = new Vector(0, 0);
|
||||
// The position and dimensions of this client's viewport.
|
||||
this.Viewport = Rectangle.Zero.clone();
|
||||
}
|
||||
|
||||
update(data) {
|
||||
// Update our local copy of this clients' name and colour (just in case)
|
||||
this.Name = data.Name;
|
||||
this.Colour = data.Colour;
|
||||
// Update the cursor position
|
||||
this.CursorPosition.x = data.CursorPosition.X;
|
||||
this.CursorPosition.y = data.CursorPosition.Y;
|
||||
// Update the viewport
|
||||
this.Viewport.x = data.Viewport.X;
|
||||
this.Viewport.y = data.Viewport.X;
|
||||
this.Viewport.width = data.Viewport.Width;
|
||||
this.Viewport.height = data.Viewport.Height;
|
||||
}
|
||||
}
|
||||
|
||||
export default OtherClient;
|
98
Nibriboard/ClientFiles/Utilities/Rectangle.js
Normal file
98
Nibriboard/ClientFiles/Utilities/Rectangle.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
"use strict";
|
||||
|
||||
import Vector from './Vector';
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rectangle in 2D space.
|
||||
/// </summary>
|
||||
public class Rectangle
|
||||
{
|
||||
/**
|
||||
* The top-left corner of the rectangle.
|
||||
* @returns {Vector}
|
||||
*/
|
||||
get TopLeft() {
|
||||
return new Vector(this.x, this.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* The top-right corner of the rectangle.
|
||||
* @returns {Vector}
|
||||
*/
|
||||
get TopRight() {
|
||||
return new Vector(this.x + this.width, this.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* The bottom-left corner of the rectangle.
|
||||
* @returns {Vector}
|
||||
*/
|
||||
get BottomLeft() {
|
||||
return new Vector(this.x, this.y + this.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* The bottom-right corner of the rectangle.
|
||||
*/
|
||||
get BottomRight() {
|
||||
return new Vector(this.x + this.width, this.y + this.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Y coordinate of the top of the rectangle.
|
||||
* @returns {Number}
|
||||
*/
|
||||
get Top {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Y coordinate of the bottom of the rectangle.
|
||||
* @returns {Number}
|
||||
*/
|
||||
get Bottom {
|
||||
return this.y + this.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* The X coordinate of the left side of the rectangle.
|
||||
* @returns {Number}
|
||||
*/
|
||||
get Left() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* The X coordinate of the right side of the rectangle.
|
||||
* @returns {Number}
|
||||
*/
|
||||
get Right() {
|
||||
return this.x + this.width;
|
||||
}
|
||||
|
||||
constructor(x, y, width, height)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this rectangle that can be safely edited without affecting the original.
|
||||
* @returns {Rectangle}
|
||||
*/
|
||||
clone()
|
||||
{
|
||||
return new Rectangle(this.x, this.y, this.width, this.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A rectangle with all it's values initalised to zero.
|
||||
* Don't forget to clone it before editing!
|
||||
* @type {Rectangle}
|
||||
*/
|
||||
Rectangle.Zero = new Rectangle(0, 0, 0, 0);)
|
||||
|
||||
export default Rectangle;
|
228
Nibriboard/ClientFiles/Utilities/Vector.js
Normal file
228
Nibriboard/ClientFiles/Utilities/Vector.js
Normal file
|
@ -0,0 +1,228 @@
|
|||
"use strict";
|
||||
|
||||
/******************************************************
|
||||
************** Simple ES6 Vector Class **************
|
||||
******************************************************
|
||||
* Author: Starbeamrainbowlabs
|
||||
* Twitter: @SBRLabs
|
||||
* Email: feedback at starbeamrainbowlabs dot com
|
||||
*
|
||||
* From https://gist.github.com/sbrl/69a8fa588865cacef9c0
|
||||
******************************************************
|
||||
* Originally written for my 2D Graphics ACW at Hull
|
||||
* University.
|
||||
******************************************************
|
||||
* Changelog
|
||||
******************************************************
|
||||
* 19th December 2015:
|
||||
* Added this changelog.
|
||||
* 28th December 2015:
|
||||
* Rewrite tests with klud.js + Node.js
|
||||
* 30th January 2016:
|
||||
* Tweak angleFrom function to make it work properly.
|
||||
* 31st January 2016:
|
||||
* Add the moveTowards function.
|
||||
* Add the minComponent getter.
|
||||
* Add the maxComponent getter.
|
||||
* Add the equalTo function.
|
||||
* Tests still need to be written for all of the above.
|
||||
* 19th September 2016:
|
||||
* Added Vector support to the multiply method.
|
||||
*/
|
||||
|
||||
class Vector {
|
||||
// Constructor
|
||||
constructor(inX, inY) {
|
||||
if(typeof inX != "number")
|
||||
throw new Error("Invalid x value.");
|
||||
if(typeof inY != "number")
|
||||
throw new Error("Invalid y value.");
|
||||
|
||||
// Store the (x, y) coordinates
|
||||
this.x = inX;
|
||||
this.y = inY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add another vector to this vector.
|
||||
* @param {Vector} v The vector to add.
|
||||
* @return {Vector} The current vector. useful for daisy-chaining calls.
|
||||
*/
|
||||
add(v) {
|
||||
this.x += v.x;
|
||||
this.y += v.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take another vector from this vector.
|
||||
* @param {Vector} v The vector to subtrace from this one.
|
||||
* @return {Vector} The current vector. useful for daisy-chaining calls.
|
||||
*/
|
||||
subtract(v) {
|
||||
this.x -= v.x;
|
||||
this.y -= v.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide the current vector by a given value.
|
||||
* @param {number} value The value to divide by.
|
||||
* @return {Vector} The current vector. Useful for daisy-chaining calls.
|
||||
*/
|
||||
divide(value) {
|
||||
if(typeof value != "number")
|
||||
throw new Error("Can't divide by non-number value.");
|
||||
|
||||
this.x /= value;
|
||||
this.y /= value;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply the current vector by a given value.
|
||||
* @param {(number|Vector)} value The number (or Vector) to multiply the current vector by.
|
||||
* @return {Vector} The current vector. useful for daisy-chaining calls.
|
||||
*/
|
||||
multiply(value) {
|
||||
if(value instanceof Vector)
|
||||
{
|
||||
this.x *= value.x;
|
||||
this.y *= value.y;
|
||||
}
|
||||
else if(typeof value == "number")
|
||||
{
|
||||
this.x *= value;
|
||||
this.y *= value;
|
||||
}
|
||||
else
|
||||
throw new Error("Can't multiply by non-number value.");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the vector towards the given vector by the given amount.
|
||||
* @param {Vector} v The vector to move towards.
|
||||
* @param {number} amount The distance to move towards the given vector.
|
||||
*/
|
||||
moveTowards(v, amount)
|
||||
{
|
||||
// From http://stackoverflow.com/a/2625107/1460422
|
||||
var dir = new Vector(
|
||||
v.x - this.x,
|
||||
v.y - this.y
|
||||
).limitTo(amount);
|
||||
this.x += dir.x;
|
||||
this.y += dir.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the length of the current vector to value without changing the
|
||||
* direction in which the vector is pointing.
|
||||
* @param {number} value The number to limit the current vector's length to.
|
||||
* @return {Vector} The current vector. useful for daisy-chaining calls.
|
||||
*/
|
||||
limitTo(value) {
|
||||
if(typeof value != "number")
|
||||
throw new Error("Can't limit to non-number value.");
|
||||
|
||||
this.divide(this.length);
|
||||
this.multiply(value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dot product of the current vector and another vector.
|
||||
* @param {Vector} v The other vector we should calculate the dot product with.
|
||||
* @return {Vector} The current vector. useful for daisy-chaining calls.
|
||||
*/
|
||||
dotProduct(v) {
|
||||
return (this.x * v.x) + (this.y * v.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the angle, in radians, from north to another vector.
|
||||
* @param {Vector} v The other vector to which to calculate the angle.
|
||||
* @return {Vector} The current vector. useful for daisy-chaining calls.
|
||||
*/
|
||||
angleFrom(v) {
|
||||
// From http://stackoverflow.com/a/16340752/1460422
|
||||
var angle = Math.atan2(v.y - this.y, v.x - this.x) - (Math.PI / 2);
|
||||
angle += Math.PI/2;
|
||||
if(angle < 0) angle += Math.PI * 2;
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the current vector.
|
||||
* @return {Vector} A clone of the current vector. Very useful for passing around copies of a vector if you don't want the original to be altered.
|
||||
*/
|
||||
clone() {
|
||||
return new Vector(this.x, this.y);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a representation of the current vector as a string.
|
||||
* @returns {string} A representation of the current vector as a string.
|
||||
*/
|
||||
toString() {
|
||||
return `(${this.x}, ${this.y})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the vector is equal to another vector.
|
||||
* @param {Vector} v The vector to compare to.
|
||||
* @return {boolean} Whether the current vector is equal to the given vector.
|
||||
*/
|
||||
equalTo(v)
|
||||
{
|
||||
if(this.x == v.x && this.y == v.y)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unit vector of the current vector - that is a vector poiting in the same direction with a length of 1. Note that this does *not* alter the original vector.
|
||||
* @return {Vector} The current vector's unit form.
|
||||
*/
|
||||
get unitVector() {
|
||||
var length = this.length;
|
||||
return new Vector(
|
||||
this.x / length,
|
||||
this.y / length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of the current vector.
|
||||
* @return {number} The length of the current vector.
|
||||
*/
|
||||
get length() {
|
||||
return Math.sqrt((this.x * this.x) + (this.y * this.y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the minimum component of the vector.
|
||||
* @return {number} The minimum component of the vector.
|
||||
*/
|
||||
get minComponent() {
|
||||
return Math.min(this.x, this.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the maximum component of the vector.
|
||||
* @return {number} The maximum component of the vector.
|
||||
*/
|
||||
get maxComponent() {
|
||||
return Math.min(this.x, this.y);
|
||||
}
|
||||
}
|
||||
|
||||
export default Vector;
|
Loading…
Reference in a new issue