diff --git a/.vs/AAWeb/v15/.suo b/.vs/AAWeb/v15/.suo
index c983a5706..4db55183e 100644
Binary files a/.vs/AAWeb/v15/.suo and b/.vs/AAWeb/v15/.suo differ
diff --git a/FloatingSpace/Bubble.js b/FloatingSpace/Bubble.js
new file mode 100644
index 000000000..86ad215af
--- /dev/null
+++ b/FloatingSpace/Bubble.js
@@ -0,0 +1,148 @@
+
+function newBubble() {
+
+ var thisObject = {
+
+ drawBackground: drawBackground,
+ drawForeground: drawForeground,
+ initialize: initialize
+
+ };
+
+ return thisObject;
+
+ function initialize(callBackFunction) {
+
+ callBackFunction();
+
+ }
+
+ function drawBackground(pFloatingObject) {
+
+ if (pFloatingObject.currentRadius > 1) {
+
+ /* Target Line */
+
+ browserCanvasContext.beginPath();
+ browserCanvasContext.moveTo(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y);
+ browserCanvasContext.lineTo(pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.x, pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.y);
+ browserCanvasContext.strokeStyle = 'rgba(204, 204, 204, 0.5)';
+ browserCanvasContext.setLineDash([4, 2]);
+ browserCanvasContext.lineWidth = 1;
+ browserCanvasContext.stroke();
+ browserCanvasContext.setLineDash([0, 0]);
+
+ }
+
+ if (pFloatingObject.currentRadius > 0.5) {
+
+ /* Target Spot */
+
+ var radius = 1;
+
+ browserCanvasContext.beginPath();
+ browserCanvasContext.arc(pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.x, pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.y, radius, 0, Math.PI * 2, true);
+ browserCanvasContext.closePath();
+ browserCanvasContext.fillStyle = 'rgba(30, 30, 30, 1)';
+ browserCanvasContext.fill();
+
+ }
+ }
+
+ function drawForeground(pFloatingObject) {
+
+ if (pFloatingObject.currentRadius > 5) {
+
+ /* Contourn */
+
+ browserCanvasContext.beginPath();
+ browserCanvasContext.arc(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y, pFloatingObject.currentRadius, 0, Math.PI * 2, true);
+ browserCanvasContext.closePath();
+ browserCanvasContext.strokeStyle = 'rgba(30, 30, 30, 0.75)';
+ browserCanvasContext.lineWidth = 1;
+ browserCanvasContext.stroke();
+
+ }
+
+ if (pFloatingObject.currentRadius > 0.5) {
+
+ /* Main FloatingObject */
+
+ var alphaA;
+
+ if (pFloatingObject.currentRadius < 3) {
+ alphaA = 1;
+ } else {
+ alphaA = 0.75;
+ }
+
+ alphaA = 0.75;
+
+ browserCanvasContext.beginPath();
+ browserCanvasContext.arc(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y, pFloatingObject.currentRadius, 0, Math.PI * 2, true);
+ browserCanvasContext.closePath();
+
+ browserCanvasContext.fillStyle = pFloatingObject.fillStyle;
+
+ browserCanvasContext.fill();
+
+ }
+
+ /* Image */
+
+ if (pFloatingObject.payload.profile.imageId !== undefined) {
+
+ let image = document.getElementById(pFloatingObject.payload.profile.imageId);
+
+ if (image !== null) {
+
+ browserCanvasContext.drawImage(image, pFloatingObject.currentPosition.x - pFloatingObject.currentImageSize / 2, pFloatingObject.currentPosition.y - pFloatingObject.currentImageSize / 2, pFloatingObject.currentImageSize, pFloatingObject.currentImageSize);
+
+ }
+ }
+
+ /* Label Text */
+
+ if (pFloatingObject.currentRadius > 6) {
+
+ browserCanvasContext.strokeStyle = pFloatingObject.labelStrokeStyle;
+
+ let labelPoint;
+ let fontSize = 10;
+
+ browserCanvasContext.font = fontSize + 'px Courier New';
+
+ let label;
+
+ label = pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].title;
+
+ if (label !== undefined) {
+
+ labelPoint = {
+ x: pFloatingObject.currentPosition.x - label.length / 2 * fontSize * 0.60,
+ y: pFloatingObject.currentPosition.y - pFloatingObject.currentImageSize / 2 - fontSize * 0.60 - 5
+ };
+
+ browserCanvasContext.font = fontSize + 'px Courier New';
+ browserCanvasContext.fillStyle = pFloatingObject.labelStrokeStyle;
+ browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y);
+
+ }
+
+ label = pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].body;
+
+ if (label !== undefined) {
+
+ labelPoint = {
+ x: pFloatingObject.currentPosition.x - label.length / 2 * fontSize * 0.60,
+ y: pFloatingObject.currentPosition.y + pFloatingObject.currentImageSize / 2 + fontSize * 0.60 + 10
+ };
+
+ browserCanvasContext.font = fontSize + 'px Courier New';
+ browserCanvasContext.fillStyle = pFloatingObject.labelStrokeStyle;
+ browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y);
+
+ }
+ }
+ }
+}
diff --git a/FloatingSpace/BubbleSets.js b/FloatingSpace/BubbleSets.js
index a43fcb350..770f2243a 100644
--- a/FloatingSpace/BubbleSets.js
+++ b/FloatingSpace/BubbleSets.js
@@ -14,7 +14,6 @@ function newBubbleSets() {
};
let bubbleSets = [];
-
let floatingLayer;
return thisObject;
@@ -36,17 +35,118 @@ function newBubbleSets() {
}
}
- function createBubbleSet(pPlotterBubbles) {
+ function createBubbleSet(pPayload, pEventHandler, callBackFunction) {
let bubbleSet = {
+ imageId: pPayload.profile.imageId,
floatingBubbles: [],
- plotterBubbles: pPlotterBubbles,
+ payload: pPayload,
handle: Math.floor((Math.random() * 10000000) + 1)
};
bubbleSets.push(bubbleSet);
- return bubbleSet.handle;
+ pEventHandler.listenToEvent("Bubbles Changed", onBubblesChanged, bubbleSets.length - 1)
+
+ callBackFunction(GLOBAL.CUSTOM_OK_RESPONSE, bubbleSet.handle);
+
+ function onBubblesChanged(pEvent, pBubbleSetIndex) {
+
+ let bubbleSet = bubbleSets[pBubbleSetIndex];
+
+ /* First we add the new bubbles. */
+
+ let newFloatingBubbles = []; // We will create a new array of Floating Bubbles as a result of this operation.
+
+ for (let i = 0; i < bubbleSet.payload.bubbles.length; i++) {
+
+ let plotterBubble = bubbleSet.payload.bubbles[i];
+ let plotterBubbleKey = plotterBubble.date.toString() + plotterBubble.rate.toString();
+ let found = false;
+
+ for (let j = 0; j < bubbleSet.floatingBubbles.length; j++) {
+
+ let floatingBubble = bubbleSet.floatingBubbles[j];
+ let floatingBubbleKey = floatingBubble.date.toString() + floatingBubble.rate.toString();
+
+ if (plotterBubbleKey === floatingBubbleKey) {
+
+ found = true;
+ break;
+
+ }
+ }
+
+ if (found === false) {
+
+ let floatingObject = newFloatingObject();
+ floatingObject.initialize("Bubble", onInitialized);
+
+ function onInitialized(err) {
+
+ floatingObject.payload = bubbleSet.payload;
+ floatingObject.payload.bubbleIndex = i;
+ floatingObject.payload.profile.imageId = bubbleSet.imageId;
+
+ //floatingObject.container = pContainer;
+
+ floatingObject.friction = .995;
+
+ floatingObject.initializeMass(100);
+ floatingObject.initializeRadius(30);
+ floatingObject.initializeImageSize(50);
+
+ floatingObject.fillStyle = 'rgba(255, 255, 255, 0.5)';
+ floatingObject.labelStrokeStyle = 'rgba(60, 60, 60, 0.50)';
+
+ floatingLayer.addFloatingObject(floatingObject);
+ plotterBubble.floatingHandle = floatingObject.handle;
+
+ }
+
+ }
+
+ newFloatingBubbles.push(plotterBubble);
+
+ }
+
+ bubbleSet.floatingBubbles = newFloatingBubbles;
+
+ /* Second we remove the old bubbles. */
+
+ newFloatingBubbles = []; // We will create a new array of Floating Bubbles as a result of this operation.
+
+ for (let j = 0; j < bubbleSet.floatingBubbles.length; j++) {
+
+ let floatingBubble = bubbleSet.floatingBubbles[j];
+ let floatingBubbleKey = floatingBubble.date.toString() + floatingBubble.rate.toString();
+
+ for (let i = 0; i < bubbleSet.payload.bubbles.length; i++) {
+
+ let plotterBubble = bubbleSet.payload.bubbles[i];
+ let plotterBubbleKey = plotterBubble.date.toString() + plotterBubble.rate.toString();
+ let found = false;
+
+ if (plotterBubbleKey === floatingBubbleKey) {
+
+ found = true;
+ break;
+
+ }
+ }
+
+ if (found === false) {
+
+ floatingLayer.removeFloatingObject(floatingBubble.floatingHandle);
+
+ } else {
+
+ newFloatingBubbles.push(floatingBubble);
+ }
+ }
+
+ bubbleSet.floatingBubbles = newFloatingBubbles;
+ }
}
function destroyBubbleSet(pHandle) {
@@ -56,6 +156,14 @@ function newBubbleSets() {
let bubbleSet = bubbleSets[i];
if (bubbleSet.handle === pHandle) {
+
+ for (let j = 0; j < bubbleSet.floatingBubbles.length; j++) {
+
+ let floatingBubble = bubbleSet.floatingBubbles[j];
+
+ floatingLayer.removeFloatingObject(floatingBubble.floatingHandle);
+ }
+
bubbleSets.splice(i, 1); // Delete item from array.
return;
}
diff --git a/FloatingSpace/FloatingLayer.js b/FloatingSpace/FloatingLayer.js
index cbe088afa..d3ca1a75c 100644
--- a/FloatingSpace/FloatingLayer.js
+++ b/FloatingSpace/FloatingLayer.js
@@ -79,13 +79,38 @@ function newFloatingLayer() {
// Gives a minimun speed towards their taget.
- if (floatingObject.currentPosition.x < floatingObject.input.position.x) {
+ let payload = {
+ position: undefined,
+ visible: false
+ };
+
+ switch (floatingObject.type) {
+
+ case "Profile Ball": {
+
+ payload.position = floatingObject.payload.profile.position;
+ payload.visible = floatingObject.payload.profile.visible;
+ break;
+ }
+ case "Bubble": {
+
+ payload.position = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].position;
+ payload.visible = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].visible;
+ break;
+ }
+ default: {
+
+ break;
+ }
+ }
+
+ if (floatingObject.currentPosition.x < payload.position.x) {
floatingObject.currentSpeed.x = floatingObject.currentSpeed.x + .005;
} else {
floatingObject.currentSpeed.x = floatingObject.currentSpeed.x - .005;
}
- if (floatingObject.currentPosition.y < floatingObject.input.position.y) {
+ if (floatingObject.currentPosition.y < payload.position.y) {
floatingObject.currentSpeed.y = floatingObject.currentSpeed.y + .005;
} else {
floatingObject.currentSpeed.y = floatingObject.currentSpeed.y - .005;
@@ -142,7 +167,7 @@ function newFloatingLayer() {
repulsionForce(i);
- gravityForce(floatingObject);
+ gravityForce(floatingObject, payload);
}
@@ -164,11 +189,36 @@ function newFloatingLayer() {
let floatingObject = innactiveFloatingObjects[i];
- if (floatingObject.input.visible === true) {
+ let payload = {
+ position: undefined,
+ visible: false
+ };
+
+ switch (floatingObject.type) {
+
+ case "Profile Ball": {
+
+ payload.position = floatingObject.payload.profile.position;
+ payload.visible = floatingObject.payload.profile.visible;
+ break;
+ }
+ case "Bubble": {
+
+ payload.position = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].position;
+ payload.visible = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].visible;
+ break;
+ }
+ default: {
+
+ break;
+ }
+ }
+
+ if (payload.visible === true) {
/* The first time that the floatingObject becomes visible, we need to do this. */
- floatingObject.radomizeCurrentPosition(floatingObject.input.position);
+ floatingObject.radomizeCurrentPosition(payload.position);
floatingObject.radomizeCurrentSpeed();
thisObject.floatingObjects.push(floatingObject);
@@ -179,14 +229,14 @@ function newFloatingLayer() {
}
}
- function gravityForce(floatingObject) {
+ function gravityForce(floatingObject, payload) {
/* We simulate a kind of gravity towards the target point of each floatingObject. This force will make the floatingObject to keep pushing to reach that point. */
const coulomb = .00001;
const minForce = 0.01;
- var d = Math.sqrt(Math.pow(floatingObject.input.position.x - floatingObject.currentPosition.x, 2) + Math.pow(floatingObject.input.position.y - floatingObject.currentPosition.y, 2)); // ... we calculate the distance ...
+ var d = Math.sqrt(Math.pow(payload.position.x - floatingObject.currentPosition.x, 2) + Math.pow(payload.position.y - floatingObject.currentPosition.y, 2)); // ... we calculate the distance ...
var force = coulomb * d * d / floatingObject.currentMass; // In this case the mass of the floatingObject affects the gravity force that it receives, that gives priority to target position to bigger floatingObjects.
@@ -200,8 +250,8 @@ function newFloatingLayer() {
};
var pos2 = {
- x: floatingObject.input.position.x,
- y: floatingObject.input.position.y
+ x: payload.position.x,
+ y: payload.position.y
};
var posDiff = { // Next we need the vector resulting from the 2 positions.
diff --git a/FloatingSpace/FloatingObject.js b/FloatingSpace/FloatingObject.js
index 433375ed7..fd9dba610 100644
--- a/FloatingSpace/FloatingObject.js
+++ b/FloatingSpace/FloatingObject.js
@@ -3,7 +3,9 @@ function newFloatingObject() {
var thisObject = {
- input: undefined, // This object contains information needed to draw the floating object, but also referenced from outside, so as to have control of the basics of the floating object.
+ payload: undefined, // This is a reference to an object controlled by a Plotter. The plotter can change its internal value and we will see them from here.
+ type: undefined, // Currently there are two types of Floating Objects: Profile Balls, and Bubbles.
+
physicsEnabled: false,
initializeMass: initializeMass,
@@ -67,6 +69,13 @@ function newFloatingObject() {
}
case "Bubble": {
+ underlayingObject = newBubble();
+ underlayingObject.initialize(onInitialized);
+
+ function onInitialized(err) {
+
+
+ }
break;
}
default: {
@@ -75,6 +84,8 @@ function newFloatingObject() {
}
}
+ thisObject.type = pType;
+
callBackFunction();
}
diff --git a/FloatingSpace/ProfileBall.js b/FloatingSpace/ProfileBall.js
index dbfa706b5..87b1d30be 100644
--- a/FloatingSpace/ProfileBall.js
+++ b/FloatingSpace/ProfileBall.js
@@ -25,7 +25,7 @@ function newProfileBall() {
browserCanvasContext.beginPath();
browserCanvasContext.moveTo(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y);
- browserCanvasContext.lineTo(pFloatingObject.input.position.x, pFloatingObject.input.position.y);
+ browserCanvasContext.lineTo(pFloatingObject.payload.profile.position.x, pFloatingObject.payload.profile.position.y);
browserCanvasContext.strokeStyle = 'rgba(204, 204, 204, 0.5)';
browserCanvasContext.setLineDash([4, 2]);
browserCanvasContext.lineWidth = 1;
@@ -41,7 +41,7 @@ function newProfileBall() {
var radius = 1;
browserCanvasContext.beginPath();
- browserCanvasContext.arc(pFloatingObject.input.position.x, pFloatingObject.input.position.y, radius, 0, Math.PI * 2, true);
+ browserCanvasContext.arc(pFloatingObject.payload.profile.position.x, pFloatingObject.payload.profile.position.y, radius, 0, Math.PI * 2, true);
browserCanvasContext.closePath();
browserCanvasContext.fillStyle = 'rgba(30, 30, 30, 1)';
browserCanvasContext.fill();
@@ -90,9 +90,9 @@ function newProfileBall() {
/* Image */
- if (pFloatingObject.input.imageId !== undefined) {
+ if (pFloatingObject.payload.profile.imageId !== undefined) {
- let image = document.getElementById(pFloatingObject.input.imageId);
+ let image = document.getElementById(pFloatingObject.payload.profile.imageId);
if (image !== null) {
@@ -114,7 +114,7 @@ function newProfileBall() {
let label;
- label = pFloatingObject.input.upLabel;
+ label = pFloatingObject.payload.profile.upLabel;
if (label !== undefined) {
@@ -129,7 +129,7 @@ function newProfileBall() {
}
- label = pFloatingObject.input.downLabel;
+ label = pFloatingObject.payload.profile.downLabel;
if (label !== undefined) {
diff --git a/FloatingSpace/ProfileBalls.js b/FloatingSpace/ProfileBalls.js
index 205a535fc..c6e7b0986 100644
--- a/FloatingSpace/ProfileBalls.js
+++ b/FloatingSpace/ProfileBalls.js
@@ -42,14 +42,14 @@ function newProfileBalls() {
}
}
- function createNewProfileBall(pInput, pContainer, callBackFunction) {
+ function createNewProfileBall(pPayload, pContainer, callBackFunction) {
let floatingObject = newFloatingObject();
floatingObject.initialize("Profile Ball", onInitialized);
function onInitialized(err) {
- floatingObject.input = pInput;
+ floatingObject.payload = pPayload;
floatingObject.container = pContainer;
diff --git a/Project.njsproj b/Project.njsproj
index b3022b5c5..3f168d3f7 100644
--- a/Project.njsproj
+++ b/Project.njsproj
@@ -32,6 +32,9 @@
+
+ Code
+
Code
diff --git a/TimelineChart.js b/TimelineChart.js
index e02aac988..6f68f278f 100644
--- a/TimelineChart.js
+++ b/TimelineChart.js
@@ -307,27 +307,33 @@
/* Create The Profie Picture FloatingObject */
- if (productPlotter.plotter.profile !== undefined) {
+ if (productPlotter.plotter.payload !== undefined) {
let imageId = pProductCard.bot.devTeam + "." + pProductCard.bot.profilePicture;
- productPlotter.plotter.profile.upLabel = pProductCard.product.shortDisplayName;
- productPlotter.plotter.profile.downLabel = pProductCard.bot.displayName;
- productPlotter.plotter.profile.imageId = imageId;
+ productPlotter.plotter.payload.profile.upLabel = pProductCard.product.shortDisplayName;
+ productPlotter.plotter.payload.profile.downLabel = pProductCard.bot.displayName;
+ productPlotter.plotter.payload.profile.imageId = imageId;
- canvas.floatingSpace.profileBalls.createNewProfileBall(productPlotter.plotter.profile, thisObject.container, onProfileBallCreated)
+ canvas.floatingSpace.profileBalls.createNewProfileBall(productPlotter.plotter.payload, thisObject.container, onProfileBallCreated)
function onProfileBallCreated(err, pProfileHandle) {
productPlotter.profile = pProfileHandle;
}
+
+ /* Create the Text Bubbles */
+
+ canvas.floatingSpace.bubbleSets.createBubbleSet(productPlotter.plotter.payload, productPlotter.plotter.container.eventHandler, onBubbleSetCreated);
+
+ function onBubbleSetCreated(err, pBubbleSetHandle) {
+
+ productPlotter.bubbleSet = pBubbleSetHandle;
+
+ }
}
- /* Create the Text Bubbles */
-
- productPlotter.bubbleSet = canvas.floatingSpace.bubbleSets.createBubbleSet(productPlotter.plotter.bubbles);
-
/* Add the new Active Protter to the Array */
productPlotters.push(productPlotter);
diff --git a/index.html b/index.html
index e26d9397b..2d7969acf 100644
--- a/index.html
+++ b/index.html
@@ -44,6 +44,7 @@
+