mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
commit
0b12812ea4
15 changed files with 736 additions and 419 deletions
63
examples/libraries/constants.js
Normal file
63
examples/libraries/constants.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/27
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
STICK_URL = HIFI_PUBLIC_BUCKET + "models/props/geo_stick.fbx";
|
||||
|
||||
ZERO_VECTOR = { x: 0, y: 0, z: 0 };
|
||||
|
||||
COLORS = {
|
||||
WHITE: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255,
|
||||
},
|
||||
BLACK: {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 0,
|
||||
},
|
||||
GREY: {
|
||||
red: 128,
|
||||
green: 128,
|
||||
blue: 128,
|
||||
},
|
||||
RED: {
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 0
|
||||
},
|
||||
BLUE: {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 255
|
||||
},
|
||||
GREEN: {
|
||||
red: 0,
|
||||
green: 255,
|
||||
blue: 0
|
||||
},
|
||||
CYAN: {
|
||||
red: 0,
|
||||
green: 255,
|
||||
blue: 255
|
||||
},
|
||||
YELLOW: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 0
|
||||
},
|
||||
MAGENTA: {
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 255
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -53,6 +53,12 @@ Highlighter.prototype.setSize = function(newSize) {
|
|||
});
|
||||
}
|
||||
|
||||
Highlighter.prototype.setRotation = function(newRotation) {
|
||||
Overlays.editOverlay(this.highlightCube, {
|
||||
rotation: newRotation
|
||||
});
|
||||
}
|
||||
|
||||
Highlighter.prototype.updateHighlight = function() {
|
||||
if (this.hightlighted) {
|
||||
var properties = Entities.getEntityProperties(this.hightlighted);
|
304
examples/libraries/omniTool.js
Normal file
304
examples/libraries/omniTool.js
Normal file
|
@ -0,0 +1,304 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/09/01
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("constants.js");
|
||||
Script.include("utils.js");
|
||||
Script.include("highlighter.js");
|
||||
Script.include("omniTool/models/modelBase.js");
|
||||
Script.include("omniTool/models/wand.js");
|
||||
|
||||
OmniToolModules = {};
|
||||
OmniToolModuleType = null;
|
||||
|
||||
OmniTool = function(side) {
|
||||
this.OMNI_KEY = "OmniTool";
|
||||
this.MAX_FRAMERATE = 30;
|
||||
this.UPDATE_INTERVAL = 1.0 / this.MAX_FRAMERATE
|
||||
this.SIDE = side;
|
||||
this.PALM = 2 * side;
|
||||
this.ACTION = findAction(side ? "ACTION2" : "ACTION1");
|
||||
this.ALT_ACTION = findAction(side ? "ACTION1" : "ACTION2");
|
||||
|
||||
this.highlighter = new Highlighter();
|
||||
this.ignoreEntities = {};
|
||||
this.nearestOmniEntity = {
|
||||
id: null,
|
||||
inside: false,
|
||||
position: null,
|
||||
distance: Infinity,
|
||||
radius: 0,
|
||||
omniProperties: {},
|
||||
boundingBox: null,
|
||||
};
|
||||
|
||||
this.activeOmniEntityId = null;
|
||||
this.lastUpdateInterval = 0;
|
||||
this.tipLength = 0.4;
|
||||
this.active = false;
|
||||
this.module = null;
|
||||
this.moduleEntityId = null;
|
||||
this.lastScanPosition = ZERO_VECTOR;
|
||||
this.model = new Wand();
|
||||
this.model.setLength(this.tipLength);
|
||||
|
||||
// Connect to desired events
|
||||
var _this = this;
|
||||
Controller.actionEvent.connect(function(action, state) {
|
||||
_this.onActionEvent(action, state);
|
||||
});
|
||||
|
||||
Script.update.connect(function(deltaTime) {
|
||||
_this.lastUpdateInterval += deltaTime;
|
||||
if (_this.lastUpdateInterval >= _this.UPDATE_INTERVAL) {
|
||||
_this.onUpdate(_this.lastUpdateInterval);
|
||||
_this.lastUpdateInterval = 0;
|
||||
}
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
_this.onCleanup();
|
||||
});
|
||||
}
|
||||
|
||||
OmniTool.prototype.onActionEvent = function(action, state) {
|
||||
// FIXME figure out the issues when only one spatial controller is active
|
||||
// logDebug("Action: " + action + " " + state);
|
||||
|
||||
if (this.module && this.module.onActionEvent) {
|
||||
this.module.onActionEvent(action, state);
|
||||
}
|
||||
|
||||
if (action == this.ACTION) {
|
||||
if (state) {
|
||||
this.onClick();
|
||||
} else {
|
||||
this.onRelease();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME Does not work
|
||||
//// with only one controller active (listed as 2 here because 'tip' + 'palm')
|
||||
//// then treat the alt action button as the action button
|
||||
}
|
||||
|
||||
OmniTool.prototype.getOmniToolData = function(entityId) {
|
||||
return getEntityCustomData(this.OMNI_KEY, entityId, null);
|
||||
}
|
||||
|
||||
OmniTool.prototype.setOmniToolData = function(entityId, data) {
|
||||
setEntityCustomData(this.OMNI_KEY, entityId, data);
|
||||
}
|
||||
|
||||
OmniTool.prototype.updateOmniToolData = function(entityId, data) {
|
||||
var currentData = this.getOmniToolData(entityId) || {};
|
||||
for (var key in data) {
|
||||
currentData[key] = data[key];
|
||||
}
|
||||
setEntityCustomData(this.OMNI_KEY, entityId, currentData);
|
||||
}
|
||||
|
||||
OmniTool.prototype.setActive = function(active) {
|
||||
if (active === this.active) {
|
||||
return;
|
||||
}
|
||||
logDebug("omnitool changing active state: " + active);
|
||||
this.active = active;
|
||||
this.model.setVisible(this.active);
|
||||
|
||||
if (this.module && this.module.onActiveChanged) {
|
||||
this.module.onActiveChanged(this.side);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OmniTool.prototype.onUpdate = function(deltaTime) {
|
||||
// FIXME this returns data if either the left or right controller is not on the base
|
||||
this.position = Controller.getSpatialControlPosition(this.PALM);
|
||||
// When on the base, hydras report a position of 0
|
||||
this.setActive(Vec3.length(this.position) > 0.001);
|
||||
|
||||
var rawRotation = Controller.getSpatialControlRawRotation(this.PALM);
|
||||
this.rotation = Quat.multiply(MyAvatar.orientation, rawRotation);
|
||||
|
||||
this.model.setTransform({
|
||||
rotation: this.rotation,
|
||||
position: this.position,
|
||||
});
|
||||
|
||||
this.scan();
|
||||
|
||||
if (this.module && this.module.onUpdate) {
|
||||
this.module.onUpdate(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
OmniTool.prototype.onClick = function() {
|
||||
// First check to see if the user is switching to a new omni module
|
||||
if (this.nearestOmniEntity.inside && this.nearestOmniEntity.omniProperties.script) {
|
||||
this.activateNewOmniModule();
|
||||
return;
|
||||
}
|
||||
|
||||
// Next check if there is an active module and if so propagate the click
|
||||
// FIXME how to I switch to a new module?
|
||||
if (this.module && this.module.onClick) {
|
||||
this.module.onClick();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
OmniTool.prototype.onRelease = function() {
|
||||
// FIXME how to I switch to a new module?
|
||||
if (this.module && this.module.onRelease) {
|
||||
this.module.onRelease();
|
||||
return;
|
||||
}
|
||||
logDebug("Base omnitool does nothing on release");
|
||||
}
|
||||
|
||||
// FIXME resturn a structure of all nearby entities to distances
|
||||
OmniTool.prototype.findNearestOmniEntity = function(maxDistance, selector) {
|
||||
if (!maxDistance) {
|
||||
maxDistance = 2.0;
|
||||
}
|
||||
var resultDistance = Infinity;
|
||||
var resultId = null;
|
||||
var resultProperties = null;
|
||||
var resultOmniData = null;
|
||||
var ids = Entities.findEntities(this.model.tipPosition, maxDistance);
|
||||
for (var i in ids) {
|
||||
var entityId = ids[i];
|
||||
if (this.ignoreEntities[entityId]) {
|
||||
continue;
|
||||
}
|
||||
var omniData = this.getOmniToolData(entityId);
|
||||
if (!omniData) {
|
||||
// FIXME find a place to flush this information
|
||||
this.ignoreEntities[entityId] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Let searchers query specifically
|
||||
if (selector && !selector(entityId, omniData)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var properties = Entities.getEntityProperties(entityId);
|
||||
var distance = Vec3.distance(this.model.tipPosition, properties.position);
|
||||
if (distance < resultDistance) {
|
||||
resultDistance = distance;
|
||||
resultId = entityId;
|
||||
}
|
||||
}
|
||||
|
||||
return resultId;
|
||||
}
|
||||
|
||||
OmniTool.prototype.getPosition = function() {
|
||||
return this.model.tipPosition;
|
||||
}
|
||||
|
||||
OmniTool.prototype.onEnterNearestOmniEntity = function() {
|
||||
this.nearestOmniEntity.inside = true;
|
||||
this.highlighter.highlight(this.nearestOmniEntity.id);
|
||||
logDebug("On enter omniEntity " + this.nearestOmniEntity.id);
|
||||
}
|
||||
|
||||
OmniTool.prototype.onLeaveNearestOmniEntity = function() {
|
||||
this.nearestOmniEntity.inside = false;
|
||||
this.highlighter.highlight(null);
|
||||
logDebug("On leave omniEntity " + this.nearestOmniEntity.id);
|
||||
}
|
||||
|
||||
OmniTool.prototype.setNearestOmniEntity = function(entityId) {
|
||||
if (entityId && entityId !== this.nearestOmniEntity.id) {
|
||||
if (this.nearestOmniEntity.id && this.nearestOmniEntity.inside) {
|
||||
this.onLeaveNearestOmniEntity();
|
||||
}
|
||||
this.nearestOmniEntity.id = entityId;
|
||||
this.nearestOmniEntity.omniProperties = this.getOmniToolData(entityId);
|
||||
var properties = Entities.getEntityProperties(entityId);
|
||||
this.nearestOmniEntity.position = properties.position;
|
||||
// FIXME use a real bounding box, not a sphere
|
||||
var bbox = properties.boundingBox;
|
||||
this.nearestOmniEntity.radius = Vec3.length(Vec3.subtract(bbox.center, bbox.brn));
|
||||
this.highlighter.setRotation(properties.rotation);
|
||||
this.highlighter.setSize(Vec3.multiply(1.05, bbox.dimensions));
|
||||
}
|
||||
}
|
||||
|
||||
OmniTool.prototype.scan = function() {
|
||||
var scanDistance = Vec3.distance(this.model.tipPosition, this.lastScanPosition);
|
||||
|
||||
if (scanDistance < 0.005) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastScanPosition = this.model.tipPosition;
|
||||
|
||||
this.setNearestOmniEntity(this.findNearestOmniEntity());
|
||||
if (this.nearestOmniEntity.id) {
|
||||
var distance = Vec3.distance(this.model.tipPosition, this.nearestOmniEntity.position);
|
||||
// track distance on a half centimeter basis
|
||||
if (Math.abs(this.nearestOmniEntity.distance - distance) > 0.005) {
|
||||
this.nearestOmniEntity.distance = distance;
|
||||
if (!this.nearestOmniEntity.inside && distance < this.nearestOmniEntity.radius) {
|
||||
this.onEnterNearestOmniEntity();
|
||||
}
|
||||
|
||||
if (this.nearestOmniEntity.inside && distance > this.nearestOmniEntity.radius + 0.01) {
|
||||
this.onLeaveNearestOmniEntity();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OmniTool.prototype.unloadModule = function() {
|
||||
if (this.module && this.module.onUnload) {
|
||||
this.module.onUnload();
|
||||
}
|
||||
this.module = null;
|
||||
this.moduleEntityId = null;
|
||||
}
|
||||
|
||||
OmniTool.prototype.activateNewOmniModule = function() {
|
||||
// Support the ability for scripts to just run without replacing the current module
|
||||
var script = this.nearestOmniEntity.omniProperties.script;
|
||||
if (script.indexOf("/") < 0) {
|
||||
script = "omniTool/modules/" + script;
|
||||
}
|
||||
|
||||
// Reset the tool type
|
||||
OmniToolModuleType = null;
|
||||
logDebug("Including script path: " + script);
|
||||
try {
|
||||
Script.include(script);
|
||||
} catch(err) {
|
||||
logWarn("Failed to include script: " + script + "\n" + err);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're building a new module, unload the old one
|
||||
if (OmniToolModuleType) {
|
||||
logDebug("New OmniToolModule: " + OmniToolModuleType);
|
||||
this.unloadModule();
|
||||
|
||||
try {
|
||||
this.module = new OmniToolModules[OmniToolModuleType](this, this.nearestOmniEntity.id);
|
||||
this.moduleEntityId = this.nearestOmniEntity.id;
|
||||
if (this.module.onLoad) {
|
||||
this.module.onLoad();
|
||||
}
|
||||
} catch(err) {
|
||||
logWarn("Failed to instantiate new module: " + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME find a good way to sync the two omni tools
|
||||
OMNI_TOOLS = [ new OmniTool(0), new OmniTool(1) ];
|
19
examples/libraries/omniTool/models/modelBase.js
Normal file
19
examples/libraries/omniTool/models/modelBase.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
ModelBase = function() {
|
||||
this.length = 0.2;
|
||||
}
|
||||
|
||||
ModelBase.prototype.setVisible = function(visible) {
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
ModelBase.prototype.setLength = function(length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
ModelBase.prototype.setTransform = function(transform) {
|
||||
this.rotation = transform.rotation;
|
||||
this.position = transform.position;
|
||||
this.tipVector = Vec3.multiplyQbyV(this.rotation, { x: 0, y: this.length, z: 0 });
|
||||
this.tipPosition = Vec3.sum(this.position, this.tipVector);
|
||||
}
|
120
examples/libraries/omniTool/models/wand.js
Normal file
120
examples/libraries/omniTool/models/wand.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
|
||||
Wand = function() {
|
||||
// Max updates fps
|
||||
this.MAX_FRAMERATE = 30
|
||||
this.UPDATE_INTERVAL = 1.0 / this.MAX_FRAMERATE
|
||||
this.DEFAULT_TIP_COLORS = [ {
|
||||
red: 128,
|
||||
green: 128,
|
||||
blue: 128,
|
||||
}, {
|
||||
red: 64,
|
||||
green: 64,
|
||||
blue: 64,
|
||||
}];
|
||||
this.POINTER_ROTATION = Quat.fromPitchYawRollDegrees(45, 0, 45);
|
||||
|
||||
// FIXME does this need to be a member of this?
|
||||
this.lastUpdateInterval = 0;
|
||||
|
||||
this.pointers = [
|
||||
Overlays.addOverlay("cube", {
|
||||
position: ZERO_VECTOR,
|
||||
color: this.DEFAULT_TIP_COLORS[0],
|
||||
alpha: 1.0,
|
||||
solid: true,
|
||||
visible: false,
|
||||
}),
|
||||
Overlays.addOverlay("cube", {
|
||||
position: ZERO_VECTOR,
|
||||
color: this.DEFAULT_TIP_COLORS[1],
|
||||
alpha: 1.0,
|
||||
solid: true,
|
||||
visible: false,
|
||||
})
|
||||
];
|
||||
|
||||
this.wand = Overlays.addOverlay("cube", {
|
||||
position: ZERO_VECTOR,
|
||||
color: COLORS.WHITE,
|
||||
dimensions: { x: 0.01, y: 0.01, z: 0.2 },
|
||||
alpha: 1.0,
|
||||
solid: true,
|
||||
visible: false
|
||||
});
|
||||
|
||||
var _this = this;
|
||||
Script.scriptEnding.connect(function() {
|
||||
Overlays.deleteOverlay(_this.pointers[0]);
|
||||
Overlays.deleteOverlay(_this.pointers[1]);
|
||||
Overlays.deleteOverlay(_this.wand);
|
||||
});
|
||||
|
||||
Script.update.connect(function(deltaTime) {
|
||||
_this.lastUpdateInterval += deltaTime;
|
||||
if (_this.lastUpdateInterval >= _this.UPDATE_INTERVAL) {
|
||||
_this.onUpdate(_this.lastUpdateInterval);
|
||||
_this.lastUpdateInterval = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Wand.prototype = Object.create( ModelBase.prototype );
|
||||
|
||||
Wand.prototype.setVisible = function(visible) {
|
||||
ModelBase.prototype.setVisible.call(this, visible);
|
||||
Overlays.editOverlay(this.pointers[0], {
|
||||
visible: this.visible
|
||||
});
|
||||
Overlays.editOverlay(this.pointers[1], {
|
||||
visible: this.visible
|
||||
});
|
||||
Overlays.editOverlay(this.wand, {
|
||||
visible: this.visible
|
||||
});
|
||||
}
|
||||
|
||||
Wand.prototype.setTransform = function(transform) {
|
||||
ModelBase.prototype.setTransform.call(this, transform);
|
||||
|
||||
var wandPosition = Vec3.sum(this.position, Vec3.multiply(0.5, this.tipVector));
|
||||
Overlays.editOverlay(this.pointers[0], {
|
||||
position: this.tipPosition,
|
||||
rotation: this.rotation,
|
||||
visible: true,
|
||||
});
|
||||
Overlays.editOverlay(this.pointers[1], {
|
||||
position: this.tipPosition,
|
||||
rotation: Quat.multiply(this.POINTER_ROTATION, this.rotation),
|
||||
visible: true,
|
||||
});
|
||||
Overlays.editOverlay(this.wand, {
|
||||
dimensions: { x: 0.01, y: this.length * 0.9, z: 0.01 },
|
||||
position: wandPosition,
|
||||
rotation: this.rotation,
|
||||
visible: true,
|
||||
});
|
||||
}
|
||||
|
||||
Wand.prototype.setTipColors = function(color1, color2) {
|
||||
Overlays.editOverlay(this.pointers[0], {
|
||||
color: color1 || this.DEFAULT_TIP_COLORS[0],
|
||||
});
|
||||
Overlays.editOverlay(this.pointers[1], {
|
||||
color: color2 || this.DEFAULT_TIP_COLORS[1],
|
||||
});
|
||||
}
|
||||
|
||||
Wand.prototype.onUpdate = function(deltaTime) {
|
||||
if (this.visible) {
|
||||
var time = new Date().getTime() / 250;
|
||||
var scale1 = Math.abs(Math.sin(time));
|
||||
var scale2 = Math.abs(Math.cos(time));
|
||||
Overlays.editOverlay(this.pointers[0], {
|
||||
scale: scale1 * 0.01,
|
||||
});
|
||||
Overlays.editOverlay(this.pointers[1], {
|
||||
scale: scale2 * 0.01,
|
||||
});
|
||||
}
|
||||
}
|
9
examples/libraries/omniTool/modules/test.js
Normal file
9
examples/libraries/omniTool/modules/test.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
OmniToolModules.Test = function() {
|
||||
}
|
||||
|
||||
OmniToolModules.Test.prototype.onClick = function() {
|
||||
logDebug("Test module onClick");
|
||||
}
|
||||
|
||||
OmniToolModuleType = "Test"
|
|
@ -53,11 +53,17 @@ getEntityUserData = function(id) {
|
|||
var results = null;
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
if (properties.userData) {
|
||||
results = JSON.parse(properties.userData);
|
||||
try {
|
||||
results = JSON.parse(properties.userData);
|
||||
} catch(err) {
|
||||
logDebug(err);
|
||||
logDebug(properties.userData);
|
||||
}
|
||||
}
|
||||
return results ? results : {};
|
||||
}
|
||||
|
||||
|
||||
// Non-destructively modify the user data of an entity.
|
||||
setEntityCustomData = function(customKey, id, data) {
|
||||
var userData = getEntityUserData(id);
|
||||
|
@ -70,14 +76,6 @@ getEntityCustomData = function(customKey, id, defaultValue) {
|
|||
return userData[customKey] ? userData[customKey] : defaultValue;
|
||||
}
|
||||
|
||||
getMagBallsData = function(id) {
|
||||
return getEntityCustomData(CUSTOM_DATA_NAME, id, {});
|
||||
}
|
||||
|
||||
setMagBallsData = function(id, value) {
|
||||
setEntityCustomData(CUSTOM_DATA_NAME, id, value);
|
||||
}
|
||||
|
||||
mergeObjects = function(proto, custom) {
|
||||
var result = {};
|
||||
for (var attrname in proto) {
|
113
examples/toys/magBalls.js
Normal file
113
examples/toys/magBalls.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/25
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// FIXME Script paths have to be relative to the caller, in this case libraries/OmniTool.js
|
||||
Script.include("../toys/magBalls/constants.js");
|
||||
Script.include("../toys/magBalls/graph.js");
|
||||
Script.include("../toys/magBalls/edgeSpring.js");
|
||||
Script.include("../toys/magBalls/magBalls.js");
|
||||
|
||||
OmniToolModuleType = "MagBallsController"
|
||||
|
||||
|
||||
OmniToolModules.MagBallsController = function(omniTool, entityId) {
|
||||
this.omniTool = omniTool;
|
||||
this.entityId = entityId;
|
||||
this.highlighter = new Highlighter();
|
||||
this.magBalls = new MagBalls();
|
||||
this.highlighter.setSize(BALL_SIZE);
|
||||
this.ghostEdges = {};
|
||||
}
|
||||
|
||||
var MAG_BALLS_DATA_NAME = "magBalls";
|
||||
|
||||
getMagBallsData = function(id) {
|
||||
return getEntityCustomData(MAG_BALLS_DATA_NAME, id, {});
|
||||
}
|
||||
|
||||
setMagBallsData = function(id, value) {
|
||||
setEntityCustomData(MAG_BALLS_DATA_NAME, id, value);
|
||||
}
|
||||
|
||||
//var magBalls = new MagBalls();
|
||||
// DEBUGGING ONLY - Clear any previous balls
|
||||
// magBalls.clear();
|
||||
|
||||
OmniToolModules.MagBallsController.prototype.onClick = function() {
|
||||
logDebug("MagBallsController onClick: " + vec3toStr(this.tipPosition));
|
||||
|
||||
this.selected = this.highlighter.hightlighted;
|
||||
logDebug("This selected: " + this.selected);
|
||||
if (!this.selected) {
|
||||
this.selected = this.magBalls.createBall(this.tipPosition);
|
||||
}
|
||||
this.magBalls.selectBall(this.selected);
|
||||
this.highlighter.highlight(null);
|
||||
logDebug("Selected " + this.selected);
|
||||
}
|
||||
|
||||
OmniToolModules.MagBallsController.prototype.onRelease = function() {
|
||||
logDebug("MagBallsController onRelease: " + vec3toStr(this.tipPosition));
|
||||
this.clearGhostEdges();
|
||||
if (this.selected) {
|
||||
this.magBalls.releaseBall(this.selected);
|
||||
this.selected = null;
|
||||
}
|
||||
}
|
||||
|
||||
OmniToolModules.MagBallsController.prototype.onUpdate = function(deltaTime) {
|
||||
this.tipPosition = this.omniTool.getPosition();
|
||||
if (!this.selected) {
|
||||
// Find the highlight target and set it.
|
||||
var target = this.magBalls.findNearestNode(this.tipPosition, BALL_SELECTION_RADIUS);
|
||||
this.highlighter.highlight(target);
|
||||
if (!target) {
|
||||
this.magBalls.onUpdate(deltaTime);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.highlighter.highlight(null);
|
||||
Entities.editEntity(this.selected, { position: this.tipPosition });
|
||||
var targetBalls = this.magBalls.findPotentialEdges(this.selected);
|
||||
for (var ballId in targetBalls) {
|
||||
if (!this.ghostEdges[ballId]) {
|
||||
// create the ovleray
|
||||
this.ghostEdges[ballId] = Overlays.addOverlay("line3d", {
|
||||
start: this.magBalls.getNodePosition(ballId),
|
||||
end: this.tipPosition,
|
||||
color: COLORS.RED,
|
||||
alpha: 1,
|
||||
lineWidth: 5,
|
||||
visible: true,
|
||||
});
|
||||
} else {
|
||||
Overlays.editOverlay(this.ghostEdges[ballId], {
|
||||
end: this.tipPosition,
|
||||
});
|
||||
}
|
||||
}
|
||||
for (var ballId in this.ghostEdges) {
|
||||
if (!targetBalls[ballId]) {
|
||||
Overlays.deleteOverlay(this.ghostEdges[ballId]);
|
||||
delete this.ghostEdges[ballId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OmniToolModules.MagBallsController.prototype.clearGhostEdges = function() {
|
||||
for(var ballId in this.ghostEdges) {
|
||||
Overlays.deleteOverlay(this.ghostEdges[ballId]);
|
||||
delete this.ghostEdges[ballId];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BallController.prototype.onUnload = function() {
|
||||
this.clearGhostEdges();
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
Script.include("handController.js");
|
||||
Script.include("highlighter.js");
|
||||
|
||||
BallController = function(side, magBalls) {
|
||||
HandController.call(this, side);
|
||||
this.magBalls = magBalls;
|
||||
this.highlighter = new Highlighter();
|
||||
this.highlighter.setSize(BALL_SIZE);
|
||||
this.ghostEdges = {};
|
||||
}
|
||||
|
||||
BallController.prototype = Object.create( HandController.prototype );
|
||||
|
||||
BallController.prototype.onUpdate = function(deltaTime) {
|
||||
HandController.prototype.onUpdate.call(this, deltaTime);
|
||||
|
||||
if (!this.selected) {
|
||||
// Find the highlight target and set it.
|
||||
var target = this.magBalls.findNearestNode(this.tipPosition, BALL_SELECTION_RADIUS);
|
||||
this.highlighter.highlight(target);
|
||||
return;
|
||||
}
|
||||
this.highlighter.highlight(null);
|
||||
Entities.editEntity(this.selected, { position: this.tipPosition });
|
||||
var targetBalls = this.magBalls.findPotentialEdges(this.selected);
|
||||
for (var ballId in targetBalls) {
|
||||
if (!this.ghostEdges[ballId]) {
|
||||
// create the ovleray
|
||||
this.ghostEdges[ballId] = Overlays.addOverlay("line3d", {
|
||||
start: this.magBalls.getNodePosition(ballId),
|
||||
end: this.tipPosition,
|
||||
color: COLORS.RED,
|
||||
alpha: 1,
|
||||
lineWidth: 5,
|
||||
visible: true,
|
||||
});
|
||||
} else {
|
||||
Overlays.editOverlay(this.ghostEdges[ballId], {
|
||||
end: this.tipPosition,
|
||||
});
|
||||
}
|
||||
}
|
||||
for (var ballId in this.ghostEdges) {
|
||||
if (!targetBalls[ballId]) {
|
||||
Overlays.deleteOverlay(this.ghostEdges[ballId]);
|
||||
delete this.ghostEdges[ballId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BallController.prototype.onClick = function() {
|
||||
this.selected = this.magBalls.grabBall(this.tipPosition, BALL_SELECTION_RADIUS);
|
||||
this.highlighter.highlight(null);
|
||||
}
|
||||
|
||||
BallController.prototype.onRelease = function() {
|
||||
this.clearGhostEdges();
|
||||
this.magBalls.releaseBall(this.selected);
|
||||
this.selected = null;
|
||||
}
|
||||
|
||||
BallController.prototype.clearGhostEdges = function() {
|
||||
for(var ballId in this.ghostEdges) {
|
||||
Overlays.deleteOverlay(this.ghostEdges[ballId]);
|
||||
delete this.ghostEdges[ballId];
|
||||
}
|
||||
}
|
||||
|
||||
BallController.prototype.onCleanup = function() {
|
||||
HandController.prototype.onCleanup.call(this);
|
||||
this.clearGhostEdges();
|
||||
}
|
||||
|
||||
BallController.prototype.onAltClick = function() {
|
||||
return;
|
||||
var target = this.magBalls.findNearestNode(this.tipPosition, BALL_SELECTION_RADIUS);
|
||||
if (!target) {
|
||||
logDebug(target);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME move to delete shape
|
||||
var toDelete = {};
|
||||
var deleteQueue = [ target ];
|
||||
while (deleteQueue.length) {
|
||||
var curNode = deleteQueue.shift();
|
||||
if (toDelete[curNode]) {
|
||||
continue;
|
||||
}
|
||||
toDelete[curNode] = true;
|
||||
for (var nodeId in this.magBalls.getConnectedNodes(curNode)) {
|
||||
deleteQueue.push(nodeId);
|
||||
}
|
||||
}
|
||||
for (var nodeId in toDelete) {
|
||||
this.magBalls.destroyNode(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BallController.prototype.onAltRelease = function() {
|
||||
}
|
|
@ -1,13 +1,3 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/27
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
STICK_URL = HIFI_PUBLIC_BUCKET + "models/props/geo_stick.fbx";
|
||||
|
||||
// FIXME make this editable through some script UI, so the user can customize the size of the structure built
|
||||
SCALE = 0.5;
|
||||
|
@ -16,60 +6,9 @@ STICK_LENGTH = 0.24 * SCALE;
|
|||
|
||||
DEBUG_MAGSTICKS = true;
|
||||
|
||||
CUSTOM_DATA_NAME = "magBalls";
|
||||
BALL_NAME = "MagBall";
|
||||
EDGE_NAME = "MagStick";
|
||||
|
||||
ZERO_VECTOR = { x: 0, y: 0, z: 0 };
|
||||
|
||||
COLORS = {
|
||||
WHITE: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255,
|
||||
},
|
||||
BLACK: {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 0,
|
||||
},
|
||||
GREY: {
|
||||
red: 128,
|
||||
green: 128,
|
||||
blue: 128,
|
||||
},
|
||||
RED: {
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 0
|
||||
},
|
||||
BLUE: {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 255
|
||||
},
|
||||
GREEN: {
|
||||
red: 0,
|
||||
green: 255,
|
||||
blue: 0
|
||||
},
|
||||
CYAN: {
|
||||
red: 0,
|
||||
green: 255,
|
||||
blue: 255
|
||||
},
|
||||
YELLOW: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 0
|
||||
},
|
||||
MAGENTA: {
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 255
|
||||
}
|
||||
}
|
||||
|
||||
BALL_RADIUS = BALL_SIZE / 2.0;
|
||||
|
||||
BALL_SELECTION_RADIUS = BALL_RADIUS * 1.5;
|
||||
|
@ -136,5 +75,3 @@ EDGE_PROTOTYPE = LINE_PROTOTYPE;
|
|||
// ignoreCollisions: true,
|
||||
// collisionsWillMove: false
|
||||
// }
|
||||
|
||||
|
||||
|
|
|
@ -101,6 +101,10 @@ Graph.prototype.getConnectedNodes = function(nodeId) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Graph.prototype.getNodesForEdge = function(edgeId) {
|
||||
return Object.keys(this.edges[edgeId]);
|
||||
}
|
||||
|
||||
Graph.prototype.getEdgeLength = function(edgeId) {
|
||||
var nodesInEdge = Object.keys(this.edges[edgeId]);
|
||||
return this.getNodeDistance(nodesInEdge[0], nodesInEdge[1]);
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/29
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
LEFT_CONTROLLER = 0;
|
||||
RIGHT_CONTROLLER = 1;
|
||||
|
||||
// FIXME add a customizable wand model and a mechanism to switch between wands
|
||||
HandController = function(side) {
|
||||
|
||||
this.side = side;
|
||||
this.palm = 2 * side;
|
||||
this.tip = 2 * side + 1;
|
||||
this.action = findAction(side ? "ACTION2" : "ACTION1");
|
||||
this.altAction = findAction(side ? "ACTION1" : "ACTION2");
|
||||
this.active = false;
|
||||
this.tipScale = 1.4;
|
||||
this.pointer = Overlays.addOverlay("sphere", {
|
||||
position: ZERO_VECTOR,
|
||||
size: 0.01,
|
||||
color: COLORS.YELLOW,
|
||||
alpha: 1.0,
|
||||
solid: true,
|
||||
visible: false,
|
||||
});
|
||||
|
||||
// Connect to desired events
|
||||
var _this = this;
|
||||
Controller.actionEvent.connect(function(action, state) {
|
||||
_this.onActionEvent(action, state);
|
||||
});
|
||||
|
||||
Script.update.connect(function(deltaTime) {
|
||||
_this.onUpdate(deltaTime);
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
_this.onCleanup();
|
||||
});
|
||||
}
|
||||
|
||||
HandController.prototype.onActionEvent = function(action, state) {
|
||||
var spatialControlCount = Controller.getNumberOfSpatialControls();
|
||||
// If only 2 spacial controls, then we only have one controller active, so use either button
|
||||
// otherwise, only use the specified action
|
||||
|
||||
if (action == this.action) {
|
||||
if (state) {
|
||||
this.onClick();
|
||||
} else {
|
||||
this.onRelease();
|
||||
}
|
||||
}
|
||||
|
||||
if (action == this.altAction) {
|
||||
if (state) {
|
||||
this.onAltClick();
|
||||
} else {
|
||||
this.onAltRelease();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HandController.prototype.setActive = function(active) {
|
||||
if (active == this.active) {
|
||||
return;
|
||||
}
|
||||
logDebug("Hand controller changing active state: " + active);
|
||||
this.active = active;
|
||||
Overlays.editOverlay(this.pointer, {
|
||||
visible: this.active
|
||||
});
|
||||
Entities.editEntity(this.wand, {
|
||||
visible: this.active
|
||||
});
|
||||
}
|
||||
|
||||
HandController.prototype.updateControllerState = function() {
|
||||
// FIXME this returns data if either the left or right controller is not on the base
|
||||
this.palmPos = Controller.getSpatialControlPosition(this.palm);
|
||||
var tipPos = Controller.getSpatialControlPosition(this.tip);
|
||||
this.tipPosition = scaleLine(this.palmPos, tipPos, this.tipScale);
|
||||
// When on the base, hydras report a position of 0
|
||||
this.setActive(Vec3.length(this.palmPos) > 0.001);
|
||||
|
||||
//logDebug(Controller.getTriggerValue(0) + " " + Controller.getTriggerValue(1));
|
||||
|
||||
//if (this.active) {
|
||||
// logDebug("#ctrls " + Controller.getNumberOfSpatialControls() + " Side: " + this.side + " Palm: " + this.palm + " " + vec3toStr(this.palmPos))
|
||||
//}
|
||||
}
|
||||
|
||||
HandController.prototype.onCleanup = function() {
|
||||
Overlays.deleteOverlay(this.pointer);
|
||||
}
|
||||
|
||||
HandController.prototype.onUpdate = function(deltaTime) {
|
||||
this.updateControllerState();
|
||||
if (this.active) {
|
||||
Overlays.editOverlay(this.pointer, {
|
||||
position: this.tipPosition
|
||||
});
|
||||
Entities.editEntity(this.wand, {
|
||||
position: this.tipPosition
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
HandController.prototype.onClick = function() {
|
||||
logDebug("Base hand controller does nothing on click");
|
||||
}
|
||||
|
||||
HandController.prototype.onRelease = function() {
|
||||
logDebug("Base hand controller does nothing on release");
|
||||
}
|
||||
|
||||
HandController.prototype.onAltClick = function() {
|
||||
logDebug("Base hand controller does nothing on alt click");
|
||||
}
|
||||
|
||||
HandController.prototype.onAltRelease = function() {
|
||||
logDebug("Base hand controller does nothing on alt click");
|
||||
}
|
||||
|
||||
|
|
@ -8,30 +8,34 @@
|
|||
|
||||
var UPDATE_INTERVAL = 0.1;
|
||||
|
||||
Script.include("graph.js");
|
||||
Script.include("edgeSpring.js");
|
||||
|
||||
// A collection of balls and edges connecting them.
|
||||
MagBalls = function() {
|
||||
Graph.call(this);
|
||||
|
||||
this.MAX_ADJUST_ITERATIONS = 100;
|
||||
this.REFRESH_WAIT_TICKS = 10;
|
||||
this.MAX_VARIANCE = 0.25;
|
||||
this.lastUpdateAge = 0;
|
||||
this.stable = false;
|
||||
this.stable = true;
|
||||
this.adjustIterations = 0;
|
||||
this.selectedNodes = {};
|
||||
this.edgeObjects = {};
|
||||
this.unstableEdges = {};
|
||||
|
||||
this.refresh();
|
||||
|
||||
var _this = this;
|
||||
Script.update.connect(function(deltaTime) {
|
||||
_this.onUpdate(deltaTime);
|
||||
});
|
||||
//Script.update.connect(function(deltaTime) {
|
||||
// _this.onUpdate(deltaTime);
|
||||
//});
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
_this.onCleanup();
|
||||
});
|
||||
|
||||
Entities.addingEntity.connect(function(entityId) {
|
||||
_this.onEntityAdded(entityId);
|
||||
});
|
||||
}
|
||||
|
||||
MagBalls.prototype = Object.create( Graph.prototype );
|
||||
|
@ -40,14 +44,23 @@ MagBalls.prototype.onUpdate = function(deltaTime) {
|
|||
this.lastUpdateAge += deltaTime;
|
||||
if (this.lastUpdateAge > UPDATE_INTERVAL) {
|
||||
this.lastUpdateAge = 0;
|
||||
if (!this.stable) {
|
||||
if (this.refreshNeeded) {
|
||||
if (++this.refreshNeeded > this.REFRESH_WAIT_TICKS) {
|
||||
logDebug("Refreshing");
|
||||
this.refresh();
|
||||
this.refreshNeeded = 0;
|
||||
}
|
||||
}
|
||||
if (!this.stable && !Object.keys(this.selectedNodes).length) {
|
||||
this.adjustIterations += 1;
|
||||
// logDebug("Update");
|
||||
var adjusted = false;
|
||||
var nodeAdjustResults = {};
|
||||
var fixupEdges = {};
|
||||
|
||||
for(var edgeId in this.edges) {
|
||||
if (!this.unstableEdges[edgeId]) {
|
||||
continue;
|
||||
}
|
||||
adjusted |= this.edgeObjects[edgeId].adjust(nodeAdjustResults);
|
||||
}
|
||||
for (var nodeId in nodeAdjustResults) {
|
||||
|
@ -72,8 +85,12 @@ MagBalls.prototype.onUpdate = function(deltaTime) {
|
|||
}, ((UPDATE_INTERVAL * 1000) / 2));
|
||||
|
||||
if (!adjusted || this.adjustIterations > this.MAX_ADJUST_ITERATIONS) {
|
||||
if (adjusted) {
|
||||
logDebug("Could not stabilized after " + this.MAX_ADJUST_ITERATIONS + " abandoning");
|
||||
}
|
||||
this.adjustIterations = 0;
|
||||
this.stable = true;
|
||||
this.unstableEdges = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +135,7 @@ MagBalls.prototype.findPotentialEdges = function(nodeId) {
|
|||
// Check distance to attempt
|
||||
var distance = this.getNodeDistance(nodeId, otherNodeId);
|
||||
var variance = this.getVariance(distance);
|
||||
if (Math.abs(variance) > 0.25) {
|
||||
if (Math.abs(variance) > this.MAX_VARIANCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -127,26 +144,38 @@ MagBalls.prototype.findPotentialEdges = function(nodeId) {
|
|||
return variances;
|
||||
}
|
||||
|
||||
MagBalls.prototype.grabBall = function(position, maxDist) {
|
||||
var selected = this.findNearestNode(position, maxDist);
|
||||
if (!selected) {
|
||||
selected = this.createNode({ position: position });
|
||||
}
|
||||
if (selected) {
|
||||
this.stable = true;
|
||||
this.breakEdges(selected);
|
||||
this.selectedNodes[selected] = true;
|
||||
}
|
||||
return selected;
|
||||
MagBalls.prototype.breakEdges = function(nodeId) {
|
||||
//var unstableNodes = this.findShape(Object.keys.target);
|
||||
//for (var node in unstableNodes) {
|
||||
// this.unstableNodes[node] = true;
|
||||
//}
|
||||
Graph.prototype.breakEdges.call(this, nodeId);
|
||||
}
|
||||
|
||||
MagBalls.prototype.createBall = function(position) {
|
||||
var created = this.createNode({ position: position });
|
||||
this.selectBall(created);
|
||||
return created;
|
||||
}
|
||||
|
||||
MagBalls.prototype.selectBall = function(selected) {
|
||||
if (!selected) {
|
||||
return;
|
||||
}
|
||||
// stop updating shapes while manipulating
|
||||
this.stable = true;
|
||||
this.selectedNodes[selected] = true;
|
||||
this.breakEdges(selected);
|
||||
}
|
||||
|
||||
|
||||
MagBalls.prototype.releaseBall = function(releasedBall) {
|
||||
delete this.selectedNodes[releasedBall];
|
||||
logDebug("Released ball: " + releasedBall);
|
||||
|
||||
var releasePosition = this.getNodePosition(releasedBall);
|
||||
this.stable = false;
|
||||
|
||||
var releasePosition = this.getNodePosition(releasedBall);
|
||||
|
||||
// iterate through the other balls and ensure we don't intersect with
|
||||
// any of them. If we do, just delete this ball and return.
|
||||
|
@ -169,10 +198,34 @@ MagBalls.prototype.releaseBall = function(releasedBall) {
|
|||
for (var otherBallId in targets) {
|
||||
this.createEdge(otherBallId, releasedBall);
|
||||
}
|
||||
|
||||
var unstableNodes = this.findShape(releasedBall);
|
||||
for (var nodeId in unstableNodes) {
|
||||
for (var edgeId in this.nodes[nodeId]) {
|
||||
this.unstableEdges[edgeId] = true;
|
||||
}
|
||||
}
|
||||
this.validate();
|
||||
}
|
||||
|
||||
|
||||
MagBalls.prototype.findShape = function(nodeId) {
|
||||
var result = {};
|
||||
var queue = [ nodeId ];
|
||||
while (queue.length) {
|
||||
var curNode = queue.shift();
|
||||
if (result[curNode]) {
|
||||
continue;
|
||||
}
|
||||
result[curNode] = true;
|
||||
for (var otherNodeId in this.getConnectedNodes(curNode)) {
|
||||
queue.push(otherNodeId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
MagBalls.prototype.getVariance = function(distance) {
|
||||
// FIXME different balls or edges might have different ideas of variance...
|
||||
// let something else handle this
|
||||
|
@ -263,8 +316,11 @@ MagBalls.prototype.refresh = function() {
|
|||
Script.setTimeout(function() {
|
||||
for (var i in deleteEdges) {
|
||||
var edgeId = deleteEdges[i];
|
||||
logDebug("deleting invalid edge " + edgeId);
|
||||
Entities.deleteEntity(edgeId);
|
||||
//logDebug("deleting invalid edge " + edgeId);
|
||||
//Entities.deleteEntity(edgeId);
|
||||
Entities.editEntity(edgeId, {
|
||||
color: COLORS.RED
|
||||
})
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
@ -291,3 +347,14 @@ MagBalls.prototype.fixupEdge = function(edgeId) {
|
|||
Entities.editEntity(edgeId, this.findEdgeParams(ballsInEdge[0], ballsInEdge[1]));
|
||||
}
|
||||
|
||||
MagBalls.prototype.onEntityAdded = function(entityId) {
|
||||
// We already have it
|
||||
if (this.nodes[entityId] || this.edges[entityId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var properties = Entities.getEntityProperties(entityId);
|
||||
if (properties.name == BALL_NAME || properties.name == EDGE_NAME) {
|
||||
this.refreshNeeded = 1;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/25
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("../../libraries/htmlColors.js");
|
||||
Script.include("constants.js");
|
||||
Script.include("utils.js");
|
||||
Script.include("magBalls.js");
|
||||
|
||||
Script.include("ballController.js");
|
||||
|
||||
var magBalls = new MagBalls();
|
||||
|
||||
// Clear any previous balls
|
||||
// magBalls.clear();
|
||||
|
||||
MenuController = function(side) {
|
||||
HandController.call(this, side);
|
||||
}
|
||||
|
||||
// FIXME resolve some of the issues with dual controllers before allowing both controllers active
|
||||
var handControllers = [new BallController(LEFT_CONTROLLER, magBalls)]; //, new HandController(RIGHT) ];
|
|
@ -1,66 +0,0 @@
|
|||
Script.include("handController.js");
|
||||
|
||||
MenuController = function(side, magBalls) {
|
||||
HandController.call(this, side);
|
||||
}
|
||||
|
||||
MenuController.prototype = Object.create( HandController.prototype );
|
||||
|
||||
MenuController.prototype.onUpdate = function(deltaTime) {
|
||||
HandController.prototype.onUpdate.call(this, deltaTime);
|
||||
if (!this.selected) {
|
||||
// Find the highlight target and set it.
|
||||
var target = this.magBalls.findNearestNode(this.tipPosition, BALL_SELECTION_RADIUS);
|
||||
this.highlighter.highlight(target);
|
||||
return;
|
||||
}
|
||||
this.highlighter.highlight(null);
|
||||
Entities.editEntity(this.selected, { position: this.tipPosition });
|
||||
var targetBalls = this.magBalls.findPotentialEdges(this.selected);
|
||||
for (var ballId in targetBalls) {
|
||||
if (!this.ghostEdges[ballId]) {
|
||||
// create the ovleray
|
||||
this.ghostEdges[ballId] = Overlays.addOverlay("line3d", {
|
||||
start: this.magBalls.getNodePosition(ballId),
|
||||
end: this.tipPosition,
|
||||
color: COLORS.RED,
|
||||
alpha: 1,
|
||||
lineWidth: 5,
|
||||
visible: true,
|
||||
});
|
||||
} else {
|
||||
Overlays.editOverlay(this.ghostEdges[ballId], {
|
||||
end: this.tipPosition,
|
||||
});
|
||||
}
|
||||
}
|
||||
for (var ballId in this.ghostEdges) {
|
||||
if (!targetBalls[ballId]) {
|
||||
Overlays.deleteOverlay(this.ghostEdges[ballId]);
|
||||
delete this.ghostEdges[ballId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuController.prototype.onClick = function() {
|
||||
this.selected = this.magBalls.grabBall(this.tipPosition, BALL_SELECTION_RADIUS);
|
||||
this.highlighter.highlight(null);
|
||||
}
|
||||
|
||||
MenuController.prototype.onRelease = function() {
|
||||
this.clearGhostEdges();
|
||||
this.magBalls.releaseBall(this.selected);
|
||||
this.selected = null;
|
||||
}
|
||||
|
||||
MenuController.prototype.clearGhostEdges = function() {
|
||||
for(var ballId in this.ghostEdges) {
|
||||
Overlays.deleteOverlay(this.ghostEdges[ballId]);
|
||||
delete this.ghostEdges[ballId];
|
||||
}
|
||||
}
|
||||
|
||||
MenuController.prototype.onCleanup = function() {
|
||||
HandController.prototype.onCleanup.call(this);
|
||||
this.clearGhostEdges();
|
||||
}
|
Loading…
Reference in a new issue