mirror of
https://github.com/JulianGro/overte.git
synced 2025-08-09 09:17:56 +02:00
* integrate support for room scale "moves as you move"
* migrate doppleganger debug controls into separate module * misc cleanup
This commit is contained in:
parent
d347eab42c
commit
7bcd9f9f95
10 changed files with 1843 additions and 250 deletions
|
@ -9,21 +9,44 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
/* eslint-env commonjs */
|
||||||
|
/* global DriveKeys, require:true, console */
|
||||||
|
/* eslint-disable comma-dangle */
|
||||||
|
|
||||||
var require = Script.require;
|
// decomment next line for automatic require cache-busting
|
||||||
|
// var require = function require(id) { return Script.require(id + '?'+new Date().getTime().toString(36)); };
|
||||||
|
if (typeof require !== 'function') {
|
||||||
|
require = Script.require;
|
||||||
|
}
|
||||||
|
|
||||||
|
var VERSION = '0.0.0';
|
||||||
var WANT_DEBUG = false;
|
var WANT_DEBUG = false;
|
||||||
|
var DEBUG_MOVE_AS_YOU_MOVE = false;
|
||||||
|
var ROTATE_AS_YOU_MOVE = false;
|
||||||
|
|
||||||
|
log(VERSION);
|
||||||
|
|
||||||
var DopplegangerClass = require('./doppleganger.js'),
|
var DopplegangerClass = require('./doppleganger.js'),
|
||||||
DopplegangerAttachments = require('./doppleganger-attachments.js'),
|
DopplegangerAttachments = require('./doppleganger-attachments.js'),
|
||||||
modelHelper = require('./model-helper.js').modelHelper;
|
DebugControls = require('./doppleganger-debug.js'),
|
||||||
|
modelHelper = require('./model-helper.js').modelHelper,
|
||||||
|
utils = require('./utils.js');
|
||||||
|
|
||||||
|
// eslint-disable-next-line camelcase
|
||||||
|
var isWebpack = typeof __webpack_require__ === 'function';
|
||||||
|
|
||||||
|
var buttonConfig = utils.assign({
|
||||||
|
text: 'MIRROR',
|
||||||
|
}, !isWebpack ? {
|
||||||
|
icon: Script.resolvePath('./doppleganger-i.svg'),
|
||||||
|
activeIcon: Script.resolvePath('./doppleganger-a.svg'),
|
||||||
|
} : {
|
||||||
|
icon: require('./doppleganger-i.svg.json'),
|
||||||
|
activeIcon: require('./doppleganger-a.svg.json'),
|
||||||
|
});
|
||||||
|
|
||||||
var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'),
|
var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'),
|
||||||
button = tablet.addButton({
|
button = tablet.addButton(buttonConfig);
|
||||||
icon: Script.resolvePath('./doppleganger-i.svg'),
|
|
||||||
activeIcon: Script.resolvePath('./doppleganger-a.svg'),
|
|
||||||
text: 'MIRROR'
|
|
||||||
});
|
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() {
|
Script.scriptEnding.connect(function() {
|
||||||
tablet.removeButton(button);
|
tablet.removeButton(button);
|
||||||
|
@ -65,6 +88,59 @@ var doppleganger = new DopplegangerClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add support for "move as you move"
|
||||||
|
{
|
||||||
|
var movementKeys = 'W,A,S,D,Up,Down,Right,Left'.split(',');
|
||||||
|
var controllerKeys = 'LX,LY,RY'.split(',');
|
||||||
|
var translationKeys = Object.keys(DriveKeys).filter(function(p) {
|
||||||
|
return /translate/i.test(p);
|
||||||
|
});
|
||||||
|
var startingPosition;
|
||||||
|
|
||||||
|
// returns an array of any active driving keys (eg: ['W', 'TRANSLATE_Z'])
|
||||||
|
function currentDrivers() {
|
||||||
|
return [].concat(
|
||||||
|
movementKeys.map(function(key) {
|
||||||
|
return Controller.getValue(Controller.Hardware.Keyboard[key]) && key;
|
||||||
|
})
|
||||||
|
).concat(
|
||||||
|
controllerKeys.map(function(key) {
|
||||||
|
return Controller.getValue(Controller.Standard[key]) !== 0.0 && key;
|
||||||
|
})
|
||||||
|
).concat(
|
||||||
|
translationKeys.map(function(key) {
|
||||||
|
return MyAvatar.getRawDriveKey(DriveKeys[key]) !== 0.0 && key;
|
||||||
|
})
|
||||||
|
).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
doppleganger.jointsUpdated.connect(function(objectID) {
|
||||||
|
var drivers = currentDrivers(),
|
||||||
|
isDriving = drivers.length > 0;
|
||||||
|
if (isDriving) {
|
||||||
|
if (startingPosition) {
|
||||||
|
debugPrint('resetting startingPosition since drivers == ', drivers.join('|'));
|
||||||
|
startingPosition = null;
|
||||||
|
}
|
||||||
|
} else if (HMD.active || DEBUG_MOVE_AS_YOU_MOVE) {
|
||||||
|
startingPosition = startingPosition || MyAvatar.position;
|
||||||
|
var movement = Vec3.subtract(MyAvatar.position, startingPosition);
|
||||||
|
startingPosition = MyAvatar.position;
|
||||||
|
// Vec3.length(movement) > 0.0001 && Vec3.print('+avatarMovement', movement);
|
||||||
|
|
||||||
|
// "mirror" the relative translation vector
|
||||||
|
movement.x *= -1;
|
||||||
|
movement.z *= -1;
|
||||||
|
var props = {};
|
||||||
|
props.position = doppleganger.position = Vec3.sum(doppleganger.position, movement);
|
||||||
|
if (ROTATE_AS_YOU_MOVE) {
|
||||||
|
props.rotation = doppleganger.orientation = MyAvatar.orientation;
|
||||||
|
}
|
||||||
|
modelHelper.editObject(doppleganger.objectID, props);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// hide the doppleganger if this client script is unloaded
|
// hide the doppleganger if this client script is unloaded
|
||||||
Script.scriptEnding.connect(doppleganger, 'stop');
|
Script.scriptEnding.connect(doppleganger, 'stop');
|
||||||
|
|
||||||
|
@ -103,15 +179,21 @@ doppleganger.modelLoaded.connect(function(error, result) {
|
||||||
|
|
||||||
// add debug indicators, but only if the user has configured the settings value
|
// add debug indicators, but only if the user has configured the settings value
|
||||||
if (Settings.getValue('debug.doppleganger', false)) {
|
if (Settings.getValue('debug.doppleganger', false)) {
|
||||||
WANT_DEBUG = true;
|
WANT_DEBUG = WANT_DEBUG || true;
|
||||||
DopplegangerClass.addDebugControls(doppleganger);
|
DopplegangerClass.WANT_DEBUG = WANT_DEBUG;
|
||||||
|
DopplegangerAttachments.WANT_DEBUG = WANT_DEBUG;
|
||||||
|
new DebugControls(doppleganger);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
(typeof console === 'object' ? console.log : print)('app-doppleganger | ' + [].slice.call(arguments).join(' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugPrint() {
|
function debugPrint() {
|
||||||
if (WANT_DEBUG) {
|
WANT_DEBUG && log.apply(this, arguments);
|
||||||
print('app-doppleganger | ' + [].slice.call(arguments).join(' '));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
UserActivityLogger.logAction('doppleganger_app_load');
|
UserActivityLogger.logAction('doppleganger_app_load');
|
||||||
|
|
1501
unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js
vendored
Normal file
1501
unpublishedScripts/marketplace/doppleganger-attachments/dist/app-doppleganger-marketplace.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,12 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
/* eslint-env commonjs */
|
/* eslint-env commonjs */
|
||||||
/* eslint-disable comma-dangle */
|
/* eslint-disable comma-dangle */
|
||||||
|
/* global console */
|
||||||
|
|
||||||
|
// var require = function(id) { return Script.require(id + '?'+new Date().getTime().toString(36)); }
|
||||||
module.exports = DopplegangerAttachments;
|
module.exports = DopplegangerAttachments;
|
||||||
|
|
||||||
DopplegangerAttachments.version = '0.0.0';
|
DopplegangerAttachments.version = '0.0.1a';
|
||||||
DopplegangerAttachments.WANT_DEBUG = false;
|
DopplegangerAttachments.WANT_DEBUG = false;
|
||||||
|
|
||||||
var _modelHelper = require('./model-helper.js'),
|
var _modelHelper = require('./model-helper.js'),
|
||||||
|
@ -13,8 +15,10 @@ var _modelHelper = require('./model-helper.js'),
|
||||||
utils = require('./utils.js');
|
utils = require('./utils.js');
|
||||||
|
|
||||||
function log() {
|
function log() {
|
||||||
print('doppleganger-attachments | ' + [].slice.call(arguments).join(' '));
|
// eslint-disable-next-line no-console
|
||||||
|
(typeof console === 'object' ? console.log : print)('doppleganger-attachments | ' + [].slice.call(arguments).join(' '));
|
||||||
}
|
}
|
||||||
|
log(DopplegangerAttachments.version);
|
||||||
|
|
||||||
function debugPrint() {
|
function debugPrint() {
|
||||||
DopplegangerAttachments.WANT_DEBUG && log.apply(this, arguments);
|
DopplegangerAttachments.WANT_DEBUG && log.apply(this, arguments);
|
||||||
|
@ -61,6 +65,9 @@ DopplegangerAttachments.prototype = {
|
||||||
},
|
},
|
||||||
// compare before / after attachment sets to determine which ones need to be (re)created
|
// compare before / after attachment sets to determine which ones need to be (re)created
|
||||||
refreshAttachments: function() {
|
refreshAttachments: function() {
|
||||||
|
if (!this.doppleganger.objectID) {
|
||||||
|
return log('refreshAttachments -- canceling; !this.doppleganger.objectID');
|
||||||
|
}
|
||||||
var before = this.attachments || [],
|
var before = this.attachments || [],
|
||||||
beforeIndex = before.reduce(function(out, att, index) {
|
beforeIndex = before.reduce(function(out, att, index) {
|
||||||
out[att.$hash] = index; return out;
|
out[att.$hash] = index; return out;
|
||||||
|
@ -90,18 +97,19 @@ DopplegangerAttachments.prototype = {
|
||||||
var attachments = this.attachments,
|
var attachments = this.attachments,
|
||||||
parentID = this.doppleganger.objectID,
|
parentID = this.doppleganger.objectID,
|
||||||
jointNames = this.doppleganger.jointNames,
|
jointNames = this.doppleganger.jointNames,
|
||||||
properties = modelHelper.getProperties(this.doppleganger.objectID);
|
properties = modelHelper.getProperties(this.doppleganger.objectID),
|
||||||
|
modelType = properties && properties.type;
|
||||||
|
utils.assert(modelType === 'model' || modelType === 'Model', 'unrecognized doppleganger modelType:' + modelType);
|
||||||
debugPrint('DopplegangerAttachments..._createAttachmentObjects', JSON.stringify({
|
debugPrint('DopplegangerAttachments..._createAttachmentObjects', JSON.stringify({
|
||||||
type: properties.type,
|
modelType: modelType,
|
||||||
attachments: attachments.length,
|
attachments: attachments.length,
|
||||||
parentID: parentID,
|
parentID: parentID,
|
||||||
jointNames: jointNames.join(' | '),
|
jointNames: jointNames.join(' | '),
|
||||||
},0,2));
|
},0,2));
|
||||||
return attachments.map(utils.bind(this, function(attachment, i) {
|
return attachments.map(utils.bind(this, function(attachment, i) {
|
||||||
var type = modelHelper.type(attachment.properties && attachment.properties.objectID);
|
var objectType = modelHelper.type(attachment.properties && attachment.properties.objectID);
|
||||||
if (type === 'overlay') {
|
if (objectType === 'overlay') {
|
||||||
debugPrint('skipping already-provisioned attachment object', type, attachment.properties && attachment.properties.name);
|
debugPrint('skipping already-provisioned attachment object', objectType, attachment.properties && attachment.properties.name);
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
var jointIndex = attachment.$jointIndex, // jointNames.indexOf(attachment.jointName),
|
var jointIndex = attachment.$jointIndex, // jointNames.indexOf(attachment.jointName),
|
||||||
|
@ -109,7 +117,7 @@ DopplegangerAttachments.prototype = {
|
||||||
|
|
||||||
attachment.properties = utils.assign({
|
attachment.properties = utils.assign({
|
||||||
name: attachment.toString(),
|
name: attachment.toString(),
|
||||||
type: properties.type,
|
type: modelType,
|
||||||
modelURL: attachment.modelUrl,
|
modelURL: attachment.modelUrl,
|
||||||
scale: scale,
|
scale: scale,
|
||||||
dimensions: modelHelper.type(parentID) === 'entity' ?
|
dimensions: modelHelper.type(parentID) === 'entity' ?
|
||||||
|
@ -123,10 +131,13 @@ DopplegangerAttachments.prototype = {
|
||||||
}, !this.manualJointSync && {
|
}, !this.manualJointSync && {
|
||||||
parentID: parentID,
|
parentID: parentID,
|
||||||
parentJointIndex: jointIndex,
|
parentJointIndex: jointIndex,
|
||||||
|
localPosition: attachment.translation,
|
||||||
|
localRotation: Quat.fromVec3Degrees(attachment.rotation),
|
||||||
});
|
});
|
||||||
var objectID = attachment.properties.objectID = modelHelper.addObject(attachment.properties);
|
var objectID = attachment.properties.objectID = modelHelper.addObject(attachment.properties);
|
||||||
|
utils.assert(!Uuid.isNull(objectID), 'could not create attachment: ' + [objectID, JSON.stringify(attachment.properties,0,2)]);
|
||||||
attachment._resource = ModelCache.prefetch(attachment.properties.modelURL);
|
attachment._resource = ModelCache.prefetch(attachment.properties.modelURL);
|
||||||
attachment._modelReadier = new ModelReadyWatcher( {
|
attachment._modelReadier = new ModelReadyWatcher({
|
||||||
resource: attachment._resource,
|
resource: attachment._resource,
|
||||||
objectID: objectID,
|
objectID: objectID,
|
||||||
});
|
});
|
||||||
|
@ -134,21 +145,23 @@ DopplegangerAttachments.prototype = {
|
||||||
|
|
||||||
attachment._modelReadier.modelReady.connect(this, function(err, result) {
|
attachment._modelReadier.modelReady.connect(this, function(err, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
log('>>>>> modelReady ERROR <<<<<: ' + err, attachment.modelUrl);
|
log('>>>>> modelReady ERROR <<<<<: ' + err, attachment.properties.modelURL);
|
||||||
modelHelper.deleteObject(objectID);
|
modelHelper.deleteObject(objectID);
|
||||||
return objectID = null;
|
return objectID = null;
|
||||||
}
|
}
|
||||||
debugPrint('attachment model ('+modelHelper.type(result.objectID)+') is ready; # joints ==',
|
debugPrint('attachment model ('+modelHelper.type(result.objectID)+') is ready; # joints ==',
|
||||||
result.jointNames && result.jointNames.length, result.naturalDimensions, result.objectID);
|
result.jointNames && result.jointNames.length, JSON.stringify(result.naturalDimensions), result.objectID);
|
||||||
var properties = modelHelper.getProperties(result.objectID),
|
var properties = modelHelper.getProperties(result.objectID),
|
||||||
naturalDimensions = attachment.properties.naturalDimensions = properties.naturalDimensions;
|
naturalDimensions = attachment.properties.naturalDimensions = properties.naturalDimensions || result.naturalDimensions;
|
||||||
modelHelper.editObject(result.objectID, {
|
modelHelper.editObject(objectID, {
|
||||||
dimensions: naturalDimensions ? Vec3.multiply(attachment.scale, naturalDimensions) : undefined,
|
dimensions: naturalDimensions ? Vec3.multiply(attachment.scale, naturalDimensions) : undefined,
|
||||||
|
localRotation: Quat.normalize({}),
|
||||||
|
localPosition: Vec3.ZERO,
|
||||||
});
|
});
|
||||||
this.onJointsUpdated(parentID); // trigger once to initialize position/rotation
|
this.onJointsUpdated(parentID); // trigger once to initialize position/rotation
|
||||||
// give time for model overlay to "settle", then make it visible
|
// give time for model overlay to "settle", then make it visible
|
||||||
Script.setTimeout(utils.bind(this, function() {
|
Script.setTimeout(utils.bind(this, function() {
|
||||||
modelHelper.editObject(result.objectID, {
|
modelHelper.editObject(objectID, {
|
||||||
visible: true,
|
visible: true,
|
||||||
});
|
});
|
||||||
attachment._loaded = true;
|
attachment._loaded = true;
|
||||||
|
@ -175,7 +188,7 @@ DopplegangerAttachments.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onJointsUpdated: function onJointsUpdated(objectID) {
|
onJointsUpdated: function onJointsUpdated(objectID, jointUpdates) {
|
||||||
var jointOrientations = modelHelper.getJointOrientations(objectID),
|
var jointOrientations = modelHelper.getJointOrientations(objectID),
|
||||||
jointPositions = modelHelper.getJointPositions(objectID),
|
jointPositions = modelHelper.getJointPositions(objectID),
|
||||||
parentID = objectID,
|
parentID = objectID,
|
||||||
|
@ -195,8 +208,9 @@ DopplegangerAttachments.prototype = {
|
||||||
jointPosition = jointPositions[jointIndex];
|
jointPosition = jointPositions[jointIndex];
|
||||||
|
|
||||||
var translation = Vec3.multiply(avatarScale, attachment.translation),
|
var translation = Vec3.multiply(avatarScale, attachment.translation),
|
||||||
rotation = Quat.fromVec3Degrees(attachment.rotation),
|
rotation = Quat.fromVec3Degrees(attachment.rotation);
|
||||||
localPosition = Vec3.multiplyQbyV(jointOrientation, translation),
|
|
||||||
|
var localPosition = Vec3.multiplyQbyV(jointOrientation, translation),
|
||||||
localRotation = rotation;
|
localRotation = rotation;
|
||||||
|
|
||||||
updates[objectID] = manualJointSync ? {
|
updates[objectID] = manualJointSync ? {
|
||||||
|
@ -212,7 +226,6 @@ DopplegangerAttachments.prototype = {
|
||||||
localPosition: localPosition,
|
localPosition: localPosition,
|
||||||
scale: attachment.scale,
|
scale: attachment.scale,
|
||||||
};
|
};
|
||||||
onJointsUpdated[objectID] = updates[objectID];
|
|
||||||
return updates;
|
return updates;
|
||||||
}, {});
|
}, {});
|
||||||
modelHelper.editObjects(updatedObjects);
|
modelHelper.editObjects(updatedObjects);
|
||||||
|
@ -221,7 +234,7 @@ DopplegangerAttachments.prototype = {
|
||||||
_initialize: function() {
|
_initialize: function() {
|
||||||
var doppleganger = this.doppleganger;
|
var doppleganger = this.doppleganger;
|
||||||
if ('$attachmentControls' in doppleganger) {
|
if ('$attachmentControls' in doppleganger) {
|
||||||
throw new Error('only one set of debug controls can be added per doppleganger');
|
throw new Error('only one set of attachment controls can be added per doppleganger');
|
||||||
}
|
}
|
||||||
doppleganger.$attachmentControls = this;
|
doppleganger.$attachmentControls = this;
|
||||||
doppleganger.activeChanged.connect(this, function(active) {
|
doppleganger.activeChanged.connect(this, function(active) {
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
// -- ADVANCED DEBUGGING --
|
||||||
|
// @function - Add debug joint indicators / extra debugging info.
|
||||||
|
// @param {Doppleganger} - existing Doppleganger instance to add controls to
|
||||||
|
//
|
||||||
|
// @note:
|
||||||
|
// * rightclick toggles mirror mode on/off
|
||||||
|
// * shift-rightclick toggles the debug indicators on/off
|
||||||
|
// * clicking on an indicator displays the joint name and mirrored joint name in the debug log.
|
||||||
|
//
|
||||||
|
// Example use:
|
||||||
|
// var doppleganger = new DopplegangerClass();
|
||||||
|
// DopplegangerClass.addDebugControls(doppleganger);
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
/* eslint-env commonjs */
|
||||||
|
/* eslint-disable comma-dangle */
|
||||||
|
/* global console */
|
||||||
|
|
||||||
|
var DopplegangerClass = require('./doppleganger.js'),
|
||||||
|
modelHelper = require('./model-helper.js').modelHelper,
|
||||||
|
utils = require('./utils.js');
|
||||||
|
|
||||||
|
module.exports = DebugControls;
|
||||||
|
// mixin addDebugControls to DopplegangerClass for backwards-compatibility
|
||||||
|
DopplegangerClass.addDebugControls = function(doppleganger) {
|
||||||
|
new DebugControls(doppleganger);
|
||||||
|
return doppleganger;
|
||||||
|
};
|
||||||
|
|
||||||
|
DebugControls.version = '0.0.0';
|
||||||
|
DebugControls.COLOR_DEFAULT = { red: 255, blue: 255, green: 255 };
|
||||||
|
DebugControls.COLOR_SELECTED = { red: 0, blue: 255, green: 0 };
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
(typeof console === 'object' ? console.log : print)('doppleganger-debug | ' + [].slice.call(arguments).join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
function DebugControls(doppleganger) {
|
||||||
|
this.enableIndicators = true;
|
||||||
|
this.selectedJointName = null;
|
||||||
|
this.debugOverlayIDs = undefined;
|
||||||
|
this.jointSelected = utils.signal(function(result) {});
|
||||||
|
this.doppleganger = doppleganger;
|
||||||
|
this._initialize();
|
||||||
|
}
|
||||||
|
DebugControls.prototype = {
|
||||||
|
start: function() {
|
||||||
|
if (!this.onMousePressEvent) {
|
||||||
|
this.onMousePressEvent = this._onMousePressEvent;
|
||||||
|
Controller.mousePressEvent.connect(this, 'onMousePressEvent');
|
||||||
|
this.doppleganger.jointsUpdated.connect(this, 'onJointsUpdated');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function() {
|
||||||
|
this.removeIndicators();
|
||||||
|
if (this.onMousePressEvent) {
|
||||||
|
this.doppleganger.jointsUpdated.disconnect(this, 'onJointsUpdated');
|
||||||
|
Controller.mousePressEvent.disconnect(this, 'onMousePressEvent');
|
||||||
|
delete this.onMousePressEvent;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createIndicators: function(jointNames) {
|
||||||
|
this.jointNames = jointNames;
|
||||||
|
return jointNames.map(function(name, i) {
|
||||||
|
return Overlays.addOverlay('shape', {
|
||||||
|
shape: 'Icosahedron',
|
||||||
|
scale: 0.1,
|
||||||
|
solid: false,
|
||||||
|
alpha: 0.5
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeIndicators: function() {
|
||||||
|
if (this.debugOverlayIDs) {
|
||||||
|
this.debugOverlayIDs.forEach(Overlays.deleteOverlay);
|
||||||
|
this.debugOverlayIDs = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onJointsUpdated: function(overlayID) {
|
||||||
|
if (!this.enableIndicators) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var jointNames = Overlays.getProperty(overlayID, 'jointNames'),
|
||||||
|
jointOrientations = Overlays.getProperty(overlayID, 'jointOrientations'),
|
||||||
|
jointPositions = Overlays.getProperty(overlayID, 'jointPositions'),
|
||||||
|
selectedIndex = jointNames.indexOf(this.selectedJointName);
|
||||||
|
|
||||||
|
if (!this.debugOverlayIDs) {
|
||||||
|
this.debugOverlayIDs = this.createIndicators(jointNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
// batch all updates into a single call (using the editOverlays({ id: {props...}, ... }) API)
|
||||||
|
var updatedOverlays = this.debugOverlayIDs.reduce(function(updates, id, i) {
|
||||||
|
updates[id] = {
|
||||||
|
position: jointPositions[i],
|
||||||
|
rotation: jointOrientations[i],
|
||||||
|
color: i === selectedIndex ? DebugControls.COLOR_SELECTED : DebugControls.COLOR_DEFAULT,
|
||||||
|
solid: i === selectedIndex
|
||||||
|
};
|
||||||
|
return updates;
|
||||||
|
}, {});
|
||||||
|
Overlays.editOverlays(updatedOverlays);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onMousePressEvent: function(evt) {
|
||||||
|
if (evt.isLeftButton) {
|
||||||
|
if (!this.enableIndicators || !this.debugOverlayIDs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var ray = Camera.computePickRay(evt.x, evt.y),
|
||||||
|
hit = Overlays.findRayIntersection(ray, true, this.debugOverlayIDs);
|
||||||
|
|
||||||
|
hit.jointIndex = this.debugOverlayIDs.indexOf(hit.overlayID);
|
||||||
|
hit.jointName = this.jointNames[hit.jointIndex];
|
||||||
|
this.jointSelected(hit);
|
||||||
|
} else if (evt.isRightButton) {
|
||||||
|
if (evt.isShifted) {
|
||||||
|
this.enableIndicators = !this.enableIndicators;
|
||||||
|
if (!this.enableIndicators) {
|
||||||
|
this.removeIndicators();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.doppleganger.mirrored = !this.doppleganger.mirrored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_initialize: function() {
|
||||||
|
if ('$debugControls' in this.doppleganger) {
|
||||||
|
throw new Error('only one set of debug controls can be added per doppleganger');
|
||||||
|
}
|
||||||
|
this.doppleganger.$debugControls = this;
|
||||||
|
|
||||||
|
this.doppleganger.activeChanged.connect(this, function(active) {
|
||||||
|
if (active) {
|
||||||
|
this.start();
|
||||||
|
} else {
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.jointSelected.connect(this, function(hit) {
|
||||||
|
this.selectedJointName = hit.jointName;
|
||||||
|
if (hit.jointIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hit.mirroredJointName = modelHelper.deriveMirroredJointNames([hit.jointName])[0];
|
||||||
|
log('selected joint:', JSON.stringify(hit, 0, 2));
|
||||||
|
});
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(this, 'removeIndicators');
|
||||||
|
},
|
||||||
|
}; // DebugControls.prototype
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
/* eslint-env commonjs */
|
/* eslint-env commonjs */
|
||||||
|
/* global console */
|
||||||
// @module doppleganger
|
// @module doppleganger
|
||||||
//
|
//
|
||||||
// This module contains the `Doppleganger` class implementation for creating an inspectable replica of
|
// This module contains the `Doppleganger` class implementation for creating an inspectable replica of
|
||||||
|
@ -24,9 +25,13 @@
|
||||||
|
|
||||||
module.exports = Doppleganger;
|
module.exports = Doppleganger;
|
||||||
|
|
||||||
|
Doppleganger.version = '0.0.1a';
|
||||||
|
log(Doppleganger.version);
|
||||||
|
|
||||||
var _modelHelper = require('./model-helper.js'),
|
var _modelHelper = require('./model-helper.js'),
|
||||||
modelHelper = _modelHelper.modelHelper,
|
modelHelper = _modelHelper.modelHelper,
|
||||||
ModelReadyWatcher = _modelHelper.ModelReadyWatcher;
|
ModelReadyWatcher = _modelHelper.ModelReadyWatcher,
|
||||||
|
utils = require('./utils.js');
|
||||||
|
|
||||||
// @property {bool} - toggle verbose debug logging on/off
|
// @property {bool} - toggle verbose debug logging on/off
|
||||||
Doppleganger.WANT_DEBUG = false;
|
Doppleganger.WANT_DEBUG = false;
|
||||||
|
@ -48,16 +53,16 @@ function Doppleganger(options) {
|
||||||
this.autoUpdate = 'autoUpdate' in options ? options.autoUpdate : true;
|
this.autoUpdate = 'autoUpdate' in options ? options.autoUpdate : true;
|
||||||
|
|
||||||
// @public
|
// @public
|
||||||
this.active = false; // whether doppleganger is currently being displayed/updated
|
this.active = false; // whether doppleganger is currently being displayed/updated
|
||||||
this.objectID = null; // current doppleganger's Overlay or Entity id
|
this.objectID = null; // current doppleganger's Overlay or Entity id
|
||||||
this.frame = 0; // current joint update frame
|
this.frame = 0; // current joint update frame
|
||||||
|
|
||||||
// @signal - emitted when .active state changes
|
// @signal - emitted when .active state changes
|
||||||
this.activeChanged = signal(function(active, reason) {});
|
this.activeChanged = utils.signal(function(active, reason) {});
|
||||||
// @signal - emitted once model is either loaded or errors out
|
// @signal - emitted once model is either loaded or errors out
|
||||||
this.modelLoaded = signal(function(error, result){});
|
this.modelLoaded = utils.signal(function(error, result){});
|
||||||
// @signal - emitted each time the model's joint data has been synchronized
|
// @signal - emitted each time the model's joint data has been synchronized
|
||||||
this.jointsUpdated = signal(function(objectID){});
|
this.jointsUpdated = utils.signal(function(objectID){});
|
||||||
}
|
}
|
||||||
|
|
||||||
Doppleganger.prototype = {
|
Doppleganger.prototype = {
|
||||||
|
@ -118,11 +123,12 @@ Doppleganger.prototype = {
|
||||||
rotations = outRotations;
|
rotations = outRotations;
|
||||||
translations = outTranslations;
|
translations = outTranslations;
|
||||||
}
|
}
|
||||||
modelHelper.editObject(this.objectID, {
|
var jointUpdates = {
|
||||||
jointRotations: rotations,
|
jointRotations: rotations,
|
||||||
jointTranslations: translations
|
jointTranslations: translations
|
||||||
});
|
};
|
||||||
this.jointsUpdated(this.objectID);
|
modelHelper.editObject(this.objectID, jointUpdates);
|
||||||
|
this.jointsUpdated(this.objectID, jointUpdates);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('.update error: '+ e, index, e.stack);
|
log('.update error: '+ e, index, e.stack);
|
||||||
this.stop('update_error');
|
this.stop('update_error');
|
||||||
|
@ -134,7 +140,7 @@ Doppleganger.prototype = {
|
||||||
// @param {vec3} [options.position=(in front of avatar)] - starting position
|
// @param {vec3} [options.position=(in front of avatar)] - starting position
|
||||||
// @param {quat} [options.orientation=avatar.orientation] - starting orientation
|
// @param {quat} [options.orientation=avatar.orientation] - starting orientation
|
||||||
start: function(options) {
|
start: function(options) {
|
||||||
options = assign(this.options, options);
|
options = utils.assign(this.options, options);
|
||||||
if (this.objectID) {
|
if (this.objectID) {
|
||||||
log('start() called but object model already exists', this.objectID);
|
log('start() called but object model already exists', this.objectID);
|
||||||
return;
|
return;
|
||||||
|
@ -194,11 +200,11 @@ Doppleganger.prototype = {
|
||||||
return this.stop(error);
|
return this.stop(error);
|
||||||
}
|
}
|
||||||
debugPrint('model ('+modelHelper.type(this.objectID)+')' + ' is ready; # joints == ' + result.jointNames.length);
|
debugPrint('model ('+modelHelper.type(this.objectID)+')' + ' is ready; # joints == ' + result.jointNames.length);
|
||||||
var naturalDimensions = modelHelper.getProperties(this.objectID, ['naturalDimensions']).naturalDimensions;
|
var naturalDimensions = this.naturalDimensions = modelHelper.getProperties(this.objectID, ['naturalDimensions']).naturalDimensions;
|
||||||
debugPrint('naturalDimensions:', JSON.stringify(naturalDimensions));
|
debugPrint('naturalDimensions:', JSON.stringify(naturalDimensions));
|
||||||
var props = { visible: true };
|
var props = { visible: true };
|
||||||
if (naturalDimensions) {
|
if (naturalDimensions) {
|
||||||
props.dimensions = Vec3.multiply(this.scale, naturalDimensions);
|
props.dimensions = this.dimensions = Vec3.multiply(this.scale, naturalDimensions);
|
||||||
}
|
}
|
||||||
debugPrint('scaledDimensions:', this.scale, JSON.stringify(props.dimensions));
|
debugPrint('scaledDimensions:', this.scale, JSON.stringify(props.dimensions));
|
||||||
modelHelper.editObject(this.objectID, props);
|
modelHelper.editObject(this.objectID, props);
|
||||||
|
@ -296,220 +302,18 @@ Doppleganger.prototype = {
|
||||||
} else {
|
} else {
|
||||||
debugPrint('creating Script.setInterval thread @ ~', Doppleganger.TARGET_FPS +'fps');
|
debugPrint('creating Script.setInterval thread @ ~', Doppleganger.TARGET_FPS +'fps');
|
||||||
var timeout = 1000 / Doppleganger.TARGET_FPS;
|
var timeout = 1000 / Doppleganger.TARGET_FPS;
|
||||||
this._interval = Script.setInterval(bind(this, 'update'), timeout);
|
this._interval = Script.setInterval(utils.bind(this, 'update'), timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// @function - bind a function to a `this` context
|
|
||||||
// @param {Object} - the `this` context
|
|
||||||
// @param {Function|String} - function or method name
|
|
||||||
function bind(thiz, method) {
|
|
||||||
method = thiz[method] || method;
|
|
||||||
return function() {
|
|
||||||
return method.apply(thiz, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// @function - Qt signal polyfill
|
|
||||||
function signal(template) {
|
|
||||||
var callbacks = [];
|
|
||||||
return Object.defineProperties(function() {
|
|
||||||
var args = [].slice.call(arguments);
|
|
||||||
callbacks.forEach(function(obj) {
|
|
||||||
obj.handler.apply(obj.scope, args);
|
|
||||||
});
|
|
||||||
}, {
|
|
||||||
connect: { value: function(scope, handler) {
|
|
||||||
var callback = {scope: scope, handler: scope[handler] || handler || scope};
|
|
||||||
if (!callback.handler || !callback.handler.apply) {
|
|
||||||
throw new Error('invalid arguments to connect:' + [template, scope, handler]);
|
|
||||||
}
|
|
||||||
callbacks.push({scope: scope, handler: scope[handler] || handler || scope});
|
|
||||||
}},
|
|
||||||
disconnect: { value: function(scope, handler) {
|
|
||||||
var match = {scope: scope, handler: scope[handler] || handler || scope};
|
|
||||||
callbacks = callbacks.filter(function(obj) {
|
|
||||||
return !(obj.scope === match.scope && obj.handler === match.handler);
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
|
|
||||||
/* eslint-disable */
|
|
||||||
function assign(target, varArgs) { // .length of function is 2
|
|
||||||
'use strict';
|
|
||||||
if (target == null) { // TypeError if undefined or null
|
|
||||||
throw new TypeError('Cannot convert undefined or null to object');
|
|
||||||
}
|
|
||||||
|
|
||||||
var to = Object(target);
|
|
||||||
|
|
||||||
for (var index = 1; index < arguments.length; index++) {
|
|
||||||
var nextSource = arguments[index];
|
|
||||||
|
|
||||||
if (nextSource != null) { // Skip over if undefined or null
|
|
||||||
for (var nextKey in nextSource) {
|
|
||||||
// Avoid bugs when hasOwnProperty is shadowed
|
|
||||||
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
|
||||||
to[nextKey] = nextSource[nextKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return to;
|
|
||||||
}
|
|
||||||
/* eslint-enable */
|
|
||||||
// //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
|
|
||||||
|
|
||||||
// @function - debug logging
|
// @function - debug logging
|
||||||
function log() {
|
function log() {
|
||||||
print('doppleganger | ' + [].slice.call(arguments).join(' '));
|
// eslint-disable-next-line no-console
|
||||||
|
(typeof console === 'object' ? console.log : print)('doppleganger | ' + [].slice.call(arguments).join(' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
function debugPrint() {
|
function debugPrint() {
|
||||||
Doppleganger.WANT_DEBUG && log.apply(this, arguments);
|
Doppleganger.WANT_DEBUG && log.apply(this, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- ADVANCED DEBUGGING --
|
|
||||||
// @function - Add debug joint indicators / extra debugging info.
|
|
||||||
// @param {Doppleganger} - existing Doppleganger instance to add controls to
|
|
||||||
//
|
|
||||||
// @note:
|
|
||||||
// * rightclick toggles mirror mode on/off
|
|
||||||
// * shift-rightclick toggles the debug indicators on/off
|
|
||||||
// * clicking on an indicator displays the joint name and mirrored joint name in the debug log.
|
|
||||||
//
|
|
||||||
// Example use:
|
|
||||||
// var doppleganger = new Doppleganger();
|
|
||||||
// Doppleganger.addDebugControls(doppleganger);
|
|
||||||
Doppleganger.addDebugControls = function(doppleganger) {
|
|
||||||
DebugControls.COLOR_DEFAULT = { red: 255, blue: 255, green: 255 };
|
|
||||||
DebugControls.COLOR_SELECTED = { red: 0, blue: 255, green: 0 };
|
|
||||||
|
|
||||||
function DebugControls() {
|
|
||||||
this.enableIndicators = true;
|
|
||||||
this.selectedJointName = null;
|
|
||||||
this.debugOverlayIDs = undefined;
|
|
||||||
this.jointSelected = signal(function(result) {});
|
|
||||||
}
|
|
||||||
DebugControls.prototype = {
|
|
||||||
start: function() {
|
|
||||||
if (!this.onMousePressEvent) {
|
|
||||||
this.onMousePressEvent = this._onMousePressEvent;
|
|
||||||
Controller.mousePressEvent.connect(this, 'onMousePressEvent');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
stop: function() {
|
|
||||||
this.removeIndicators();
|
|
||||||
if (this.onMousePressEvent) {
|
|
||||||
Controller.mousePressEvent.disconnect(this, 'onMousePressEvent');
|
|
||||||
delete this.onMousePressEvent;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
createIndicators: function(jointNames) {
|
|
||||||
this.jointNames = jointNames;
|
|
||||||
return jointNames.map(function(name, i) {
|
|
||||||
return Overlays.addOverlay('shape', {
|
|
||||||
shape: 'Icosahedron',
|
|
||||||
scale: 0.1,
|
|
||||||
solid: false,
|
|
||||||
alpha: 0.5
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeIndicators: function() {
|
|
||||||
if (this.debugOverlayIDs) {
|
|
||||||
this.debugOverlayIDs.forEach(Overlays.deleteOverlay);
|
|
||||||
this.debugOverlayIDs = undefined;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onJointsUpdated: function(overlayID) {
|
|
||||||
if (!this.enableIndicators) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var jointNames = Overlays.getProperty(overlayID, 'jointNames'),
|
|
||||||
jointOrientations = Overlays.getProperty(overlayID, 'jointOrientations'),
|
|
||||||
jointPositions = Overlays.getProperty(overlayID, 'jointPositions'),
|
|
||||||
selectedIndex = jointNames.indexOf(this.selectedJointName);
|
|
||||||
|
|
||||||
if (!this.debugOverlayIDs) {
|
|
||||||
this.debugOverlayIDs = this.createIndicators(jointNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
// batch all updates into a single call (using the editOverlays({ id: {props...}, ... }) API)
|
|
||||||
var updatedOverlays = this.debugOverlayIDs.reduce(function(updates, id, i) {
|
|
||||||
updates[id] = {
|
|
||||||
position: jointPositions[i],
|
|
||||||
rotation: jointOrientations[i],
|
|
||||||
color: i === selectedIndex ? DebugControls.COLOR_SELECTED : DebugControls.COLOR_DEFAULT,
|
|
||||||
solid: i === selectedIndex
|
|
||||||
};
|
|
||||||
return updates;
|
|
||||||
}, {});
|
|
||||||
Overlays.editOverlays(updatedOverlays);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onMousePressEvent: function(evt) {
|
|
||||||
if (!evt.isLeftButton || !this.enableIndicators || !this.debugOverlayIDs) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var ray = Camera.computePickRay(evt.x, evt.y),
|
|
||||||
hit = Overlays.findRayIntersection(ray, true, this.debugOverlayIDs);
|
|
||||||
|
|
||||||
hit.jointIndex = this.debugOverlayIDs.indexOf(hit.overlayID);
|
|
||||||
hit.jointName = this.jointNames[hit.jointIndex];
|
|
||||||
this.jointSelected(hit);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if ('$debugControls' in doppleganger) {
|
|
||||||
throw new Error('only one set of debug controls can be added per doppleganger');
|
|
||||||
}
|
|
||||||
var debugControls = new DebugControls();
|
|
||||||
doppleganger.$debugControls = debugControls;
|
|
||||||
|
|
||||||
function onMousePressEvent(evt) {
|
|
||||||
if (evt.isRightButton) {
|
|
||||||
if (evt.isShifted) {
|
|
||||||
debugControls.enableIndicators = !debugControls.enableIndicators;
|
|
||||||
if (!debugControls.enableIndicators) {
|
|
||||||
debugControls.removeIndicators();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
doppleganger.mirrored = !doppleganger.mirrored;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doppleganger.activeChanged.connect(function(active) {
|
|
||||||
if (active) {
|
|
||||||
debugControls.start();
|
|
||||||
doppleganger.jointsUpdated.connect(debugControls, 'onJointsUpdated');
|
|
||||||
Controller.mousePressEvent.connect(onMousePressEvent);
|
|
||||||
} else {
|
|
||||||
Controller.mousePressEvent.disconnect(onMousePressEvent);
|
|
||||||
doppleganger.jointsUpdated.disconnect(debugControls, 'onJointsUpdated');
|
|
||||||
debugControls.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
debugControls.jointSelected.connect(function(hit) {
|
|
||||||
debugControls.selectedJointName = hit.jointName;
|
|
||||||
if (hit.jointIndex < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hit.mirroredJointName = modelHelper.deriveMirroredJointNames([hit.jointName])[0];
|
|
||||||
log('selected joint:', JSON.stringify(hit, 0, 2));
|
|
||||||
});
|
|
||||||
|
|
||||||
Script.scriptEnding.connect(debugControls, 'removeIndicators');
|
|
||||||
|
|
||||||
return doppleganger;
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
all:
|
||||||
|
@echo "make dist"
|
||||||
|
|
||||||
|
dist: doppleganger-a.svg.json doppleganger-i.svg.json dist/app-doppleganger-marketplace.js
|
||||||
|
@echo "OK"
|
||||||
|
|
||||||
|
%.svg.json: %.svg
|
||||||
|
cat $< | jq -sR '"data:image/svg+xml;xml,"+.' > $@
|
||||||
|
|
||||||
|
dist/app-doppleganger-marketplace.js: *.js
|
||||||
|
./node_modules/.bin/webpack --verbose app-doppleganger-attachments.js $@
|
|
@ -8,6 +8,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
/* eslint-env commonjs */
|
/* eslint-env commonjs */
|
||||||
|
/* global console */
|
||||||
// @module model-helper
|
// @module model-helper
|
||||||
//
|
//
|
||||||
// This module provides ModelReadyWatcher (a helper class for knowing when a model becomes usable inworld) and
|
// This module provides ModelReadyWatcher (a helper class for knowing when a model becomes usable inworld) and
|
||||||
|
@ -18,10 +19,16 @@ var utils = require('./utils.js'),
|
||||||
assert = utils.assert;
|
assert = utils.assert;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
version: '0.0.0',
|
version: '0.0.1',
|
||||||
ModelReadyWatcher: ModelReadyWatcher
|
ModelReadyWatcher: ModelReadyWatcher
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
(typeof console === 'object' ? console.log : print)('model-helper | ' + [].slice.call(arguments).join(' '));
|
||||||
|
}
|
||||||
|
log(module.exports.version);
|
||||||
|
|
||||||
var _objectDeleted = utils.signal(function objectDeleted(objectID){});
|
var _objectDeleted = utils.signal(function objectDeleted(objectID){});
|
||||||
// proxy for _objectDeleted that only binds deletion tracking if script actually connects to the unified signal
|
// proxy for _objectDeleted that only binds deletion tracking if script actually connects to the unified signal
|
||||||
var objectDeleted = utils.assign(function objectDeleted(objectID){}, {
|
var objectDeleted = utils.assign(function objectDeleted(objectID){}, {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"webpack": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
note: to rebuild webpack version:
|
||||||
|
* install `jq` https://stedolan.github.io/jq (used to encode the icon.svg's as Data URI JSON strings)
|
||||||
|
* `npm install`
|
||||||
|
* `make dist`
|
|
@ -1,12 +1,20 @@
|
||||||
/* eslint-env commonjs */
|
/* eslint-env commonjs */
|
||||||
|
/* global console */
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
version: '0.0.1',
|
||||||
bind: bind,
|
bind: bind,
|
||||||
signal: signal,
|
signal: signal,
|
||||||
assign: assign,
|
assign: assign,
|
||||||
assert: assert
|
assert: assert
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
(typeof console === 'object' ? console.log : print)('utils | ' + [].slice.call(arguments).join(' '));
|
||||||
|
}
|
||||||
|
log(module.exports.version);
|
||||||
|
|
||||||
// @function - bind a function to a `this` context
|
// @function - bind a function to a `this` context
|
||||||
// @param {Object} - the `this` context
|
// @param {Object} - the `this` context
|
||||||
// @param {Function|String} - function or method name
|
// @param {Function|String} - function or method name
|
||||||
|
|
Loading…
Reference in a new issue