Merge branch 'master' of https://github.com/highfidelity/hifi into editHandleDebugWindowFix

This commit is contained in:
David Back 2018-06-14 13:14:24 -07:00
commit 3be477e7f2
55 changed files with 2359 additions and 1278 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -171,6 +171,10 @@ FocusScope {
}
}
function textAt(index) {
return comboBox.textAt(index);
}
HifiControls.Label {
id: comboBoxLabel
text: root.label

View file

@ -17,6 +17,10 @@ import "../controls-uit" as HifiControls
SpinBox {
id: spinBox
HifiConstants {
id: hifi
}
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
property string label: ""
@ -31,8 +35,8 @@ SpinBox {
property real maximumValue: 0.0
property real realValue: 0.0
property real realFrom: 0.0
property real realTo: 100.0
property real realFrom: minimumValue
property real realTo: maximumValue
property real realStepSize: 1.0
signal editingFinished()
@ -53,7 +57,8 @@ SpinBox {
onValueChanged: realValue = value/factor
stepSize: realStepSize*factor
value: realValue*factor
value: Math.round(realValue*factor)
to : realTo*factor
from : realFrom*factor
@ -81,6 +86,7 @@ SpinBox {
}
valueFromText: function(text, locale) {
spinBox.value = 0; // Force valueChanged signal to be emitted so that validator fires.
return Number.fromLocaleString(locale, text)*factor;
}
@ -110,7 +116,7 @@ SpinBox {
anchors.centerIn: parent
text: hifi.glyphs.caratUp
size: hifi.dimensions.spinnerSize
color: spinBox.down.pressed || spinBox.up.hovered ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
color: spinBox.up.pressed || spinBox.up.hovered ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
}
}
@ -149,26 +155,14 @@ SpinBox {
visible: spinBox.labelInside != ""
}
// MouseArea {
// anchors.fill: parent
// propagateComposedEvents: true
// onWheel: {
// if(spinBox.activeFocus)
// wheel.accepted = false
// else
// wheel.accepted = true
// }
// onPressed: {
// mouse.accepted = false
// }
// onReleased: {
// mouse.accepted = false
// }
// onClicked: {
// mouse.accepted = false
// }
// onDoubleClicked: {
// mouse.accepted = false
// }
// }
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
onWheel: {
if (wheel.angleDelta.y > 0)
value += stepSize
else
value -= stepSize
}
}
}

View file

@ -119,8 +119,8 @@ Item {
colorScheme: hifi.colorSchemes.dark
currentIndex: attachment ? model.indexOf(attachment.jointName) : -1
onCurrentIndexChanged: {
if (completed && attachment && currentIndex != -1 && currentText && currentText !== attachment.jointName) {
attachment.jointName = currentText;
if (completed && attachment && currentIndex != -1 && attachment.jointName !== model[currentIndex]) {
attachment.jointName = model[currentIndex];
updateAttachment();
}
}

View file

@ -69,10 +69,15 @@ Item {
id: stack
initialItem: inputConfiguration
property alias messageVisible: imageMessageBox.visible
property alias selectedPlugin: box.currentText
Rectangle {
id: inputConfiguration
anchors.fill: parent
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: 230
HifiConstants { id: hifi }
@ -168,7 +173,7 @@ Item {
text: "show all input devices"
onClicked: {
inputPlugins();
box.model = inputPlugins();
changeSource();
}
}
@ -208,25 +213,28 @@ Item {
anchors.leftMargin: 10
anchors.topMargin: 30
}
}
Rectangle {
id: loaderRectangle
z: -1
color: hifi.colors.baseGray
width: parent.width
anchors.left: parent.left
anchors.right: parent.right
anchors.top: inputConfiguration.bottom
anchors.bottom: parent.bottom
Loader {
id: loader
asynchronous: false
width: inputConfiguration.width
anchors.left: inputConfiguration.left
anchors.right: inputConfiguration.right
anchors.top: configurationHeader.bottom
anchors.topMargin: 10
anchors.bottom: inputConfiguration.bottom
source: InputConfiguration.configurationLayout(box.currentText);
anchors.fill: parent
source: InputConfiguration.configurationLayout(box.textAt(box.currentIndex));
onLoaded: {
if (loader.item.hasOwnProperty("pluginName")) {
if (box.currentText === "HTC Vive") {
if (box.textAt(box.currentIndex) === "HTC Vive") {
loader.item.pluginName = "OpenVR";
} else {
loader.item.pluginName = box.currentText;
loader.item.pluginName = box.textAt(box.currentIndex);
}
}
@ -252,11 +260,12 @@ Item {
function changeSource() {
loader.source = "";
var selectedDevice = box.textAt(box.currentIndex);
var source = "";
if (box.currentText == "Vive") {
if (selectedDevice == "HTC Vive") {
source = InputConfiguration.configurationLayout("OpenVR");
} else {
source = InputConfiguration.configurationLayout(box.currentText);
source = InputConfiguration.configurationLayout(selectedDevice);
}
loader.source = source;

File diff suppressed because it is too large Load diff

View file

@ -56,7 +56,8 @@ class QScriptEngine;
* @property {Uuid} tabletID - The UUID of the tablet body model overlay.
* @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay.
* @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay.
* @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight overlay.
* @property {Uuid} homeButtonHighlightMaterialID - The UUID of the material entity used to highlight tablet button
* @property {Uuid} homeButtonUnhighlightMaterialID - The UUID of the material entity use to unhighlight the entity
*/
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
Q_OBJECT
@ -67,8 +68,9 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
Q_PROPERTY(bool tabletContextualMode READ getTabletContextualMode)
Q_PROPERTY(QUuid tabletID READ getCurrentTabletFrameID WRITE setCurrentTabletFrameID)
Q_PROPERTY(QUuid homeButtonID READ getCurrentHomeButtonID WRITE setCurrentHomeButtonID)
Q_PROPERTY(QUuid homeButtonHighlightID READ getCurrentHomeButtonHightlightID WRITE setCurrentHomeButtonHightlightID)
Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID)
Q_PROPERTY(QUuid homeButtonHighlightMaterialID READ getCurrentHomeButtonHighlightMaterialID WRITE setCurrentHomeButtonHighlightMaterialID)
Q_PROPERTY(QUuid homeButtonUnhighlightMaterialID READ getCurrentHomeButtonUnhighlightMaterialID WRITE setCurrentHomeButtonUnhighlightMaterialID)
public:
@ -372,20 +374,24 @@ public:
void setCurrentHomeButtonID(QUuid homeButtonID) { _homeButtonID = homeButtonID; }
QUuid getCurrentHomeButtonID() const { return _homeButtonID; }
void setCurrentHomeButtonHightlightID(QUuid homeButtonHightlightID) { _homeButtonHightlightID = homeButtonHightlightID; }
QUuid getCurrentHomeButtonHightlightID() const { return _homeButtonHightlightID; }
void setCurrentTabletScreenID(QUuid tabletID) { _tabletScreenID = tabletID; }
QUuid getCurrentTabletScreenID() const { return _tabletScreenID; }
void setCurrentHomeButtonHighlightMaterialID(QUuid homeButtonHighlightMaterialID) { _homeButtonHighlightMaterialID = homeButtonHighlightMaterialID; }
QUuid getCurrentHomeButtonHighlightMaterialID() { return _homeButtonHighlightMaterialID; }
void setCurrentHomeButtonUnhighlightMaterialID(QUuid homeButtonUnhighlightMaterialID) { _homeButtonUnhighlightMaterialID = homeButtonUnhighlightMaterialID; }
QUuid getCurrentHomeButtonUnhighlightMaterialID() { return _homeButtonUnhighlightMaterialID; }
private:
bool _showTablet { false };
bool _tabletContextualMode { false };
QUuid _tabletUIID; // this is the entityID of the tablet frame
QUuid _tabletScreenID; // this is the overlayID which is part of (a child of) the tablet-ui.
QUuid _homeButtonID;
QUuid _homeButtonHightlightID;
QUuid _tabletEntityID;
QUuid _homeButtonHighlightMaterialID;
QUuid _homeButtonUnhighlightMaterialID;
// Get the position of the HMD
glm::vec3 getPosition() const;

View file

@ -182,7 +182,7 @@ public:
/**jsdoc
* Get the list of avatars, entities, and overlays stored in a selection list.
* @function Selection.getList
* @function Selection.getSelectedItemsList
* @param {string} listName - The name of the selection list.
* @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
* returns an empty object with no properties.
@ -257,7 +257,7 @@ public:
void onSelectedItemsListChanged(const QString& listName);
signals:
/**jsoc
/**jsdoc
* Triggered when a list's content changes.
* @function Selection.selectedItemsListChanged
* @param {string} listName - The name of the selection list that changed.

View file

@ -283,7 +283,7 @@ QVariant Base3DOverlay::getProperty(const QString& property) {
}
bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
return false;
}

View file

@ -69,11 +69,11 @@ public:
virtual QVariant getProperty(const QString& property) override;
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal);
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false);
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo) {
return findRayIntersection(origin, direction, distance, face, surfaceNormal);
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) {
return findRayIntersection(origin, direction, distance, face, surfaceNormal, precisionPicking);
}
virtual SpatialParentTree* getParentTree() const override;

View file

@ -521,7 +521,7 @@ QVariant Circle3DOverlay::getProperty(const QString& property) {
}
bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) {
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
// Scale the dimensions by the diameter
glm::vec2 dimensions = getOuterRadius() * 2.0f * getDimensions();

View file

@ -55,7 +55,7 @@ public:
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override;
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
virtual Circle3DOverlay* createClone() const override;

View file

@ -35,7 +35,7 @@ public:
virtual Grid3DOverlay* createClone() const override;
// Grids are UI tools, and may not be intersected (pickable)
virtual bool findRayIntersection(const glm::vec3&, const glm::vec3&, float&, BoxFace&, glm::vec3&) override { return false; }
virtual bool findRayIntersection(const glm::vec3&, const glm::vec3&, float&, BoxFace&, glm::vec3&, bool precisionPicking = false) override { return false; }
protected:
Transform evalRenderTransform() override;

View file

@ -258,7 +258,7 @@ void Image3DOverlay::setURL(const QString& url) {
}
bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
if (_texture && _texture->isLoaded()) {
// Make sure position and rotation is updated.
Transform transform = getTransform();

View file

@ -43,7 +43,7 @@ public:
bool isTransparent() override { return Base3DOverlay::isTransparent() || _alphaTexture; }
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override;
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
virtual Image3DOverlay* createClone() const override;

View file

@ -509,16 +509,16 @@ QVariant ModelOverlay::getProperty(const QString& property) {
}
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
QVariantMap extraInfo;
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo);
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo, precisionPicking);
}
bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo) {
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) {
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo);
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo, precisionPicking);
}
ModelOverlay* ModelOverlay::createClone() const {

View file

@ -45,9 +45,9 @@ public:
void setProperties(const QVariantMap& properties) override;
QVariant getProperty(const QString& property) override;
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override;
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo) override;
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) override;
virtual ModelOverlay* createClone() const override;

View file

@ -554,7 +554,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay
glm::vec3 thisSurfaceNormal;
QVariantMap thisExtraInfo;
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
thisFace, thisSurfaceNormal, thisExtraInfo)) {
thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) {
bool isDrawInFront = thisOverlay->getDrawInFront();
if ((bestIsFront && isDrawInFront && thisDistance < bestDistance)
|| (!bestIsFront && (isDrawInFront || thisDistance < bestDistance))) {

View file

@ -71,7 +71,7 @@ QVariant Planar3DOverlay::getProperty(const QString& property) {
}
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
// FIXME - face and surfaceNormal not being returned
return findRayRectangleIntersection(origin, direction, getWorldOrientation(), getWorldPosition(), getDimensions(), distance);
}

View file

@ -31,7 +31,7 @@ public:
virtual QVariant getProperty(const QString& property) override;
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override;
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
protected:
glm::vec2 _dimensions;

View file

@ -76,7 +76,7 @@ QVariant Volume3DOverlay::getProperty(const QString& property) {
}
bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
// extents is the entity relative, scaled, centered extents of the entity
glm::mat4 worldToEntityMatrix;
Transform transform = getTransform();

View file

@ -31,7 +31,7 @@ public:
QVariant getProperty(const QString& property) override;
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override;
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
protected:
// Centered local bounding box

View file

@ -622,7 +622,7 @@ void Web3DOverlay::setScriptURL(const QString& scriptURL) {
}
}
bool Web3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
bool Web3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
glm::vec2 dimensions = getDimensions();
glm::quat rotation = getWorldOrientation();
glm::vec3 position = getWorldPosition();

View file

@ -53,7 +53,7 @@ public:
QVariant getProperty(const QString& property) override;
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override;
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
virtual Web3DOverlay* createClone() const override;

View file

@ -815,8 +815,13 @@ unsigned int LimitedNodeList::broadcastToNodes(std::unique_ptr<NLPacket> packet,
eachNode([&](const SharedNodePointer& node){
if (node && destinationNodeTypes.contains(node->getType())) {
sendUnreliablePacket(*packet, *node);
++n;
if (packet->isReliable()) {
auto packetCopy = NLPacket::createCopy(*packet);
sendPacket(std::move(packetCopy), *node);
} else {
sendUnreliablePacket(*packet, *node);
}
++n;
}
});

View file

@ -0,0 +1,103 @@
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import "qrc:////qml//styles-uit" as HifiStylesUit
import "qrc:////qml//controls-uit" as HifiControlsUit
//uncomment to use from qmlscratch tool
//import '../../../interface/resources/qml/controls-uit' as HifiControlsUit
//import '../../../interface/resources/qml/styles-uit'
//uncomment to use with HIFI_USE_SOURCE_TREE_RESOURCES=1
//import '../../../resources/qml/controls-uit' as HifiControlsUit
//import '../../../resources/qml/styles-uit'
Item {
visible: true
width: 640
height: 480
Introspector {
id: introspector
properties: ['realFrom', 'realTo', 'realValue', 'realStepSize', 'decimals']
visible: true
y: 50
x: 130
}
HifiStylesUit.HifiConstants {
id: hifi
}
TabBar {
id: bar
width: parent.width
TabButton {
text: "Spinbox"
}
TabButton {
text: "... Other Controls"
}
}
StackLayout {
id: controlsLayout
currentIndex: bar.currentIndex
anchors.top: bar.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 20
Item {
id: spinboxTab
anchors.fill: parent
Column {
spacing: 20
HifiControlsUit.SpinBox {
realValue: 5.0
realFrom: 16.0
realTo: 20.0
decimals: 2
realStepSize: 0.01
width: 100
height: 30
colorScheme: hifi.colorSchemes.dark
onFocusChanged: {
if(focus) {
introspector.object = this
}
}
}
HifiControlsUit.SpinBox {
realValue: 5.0
realFrom: 1.0
realTo: 20.0
decimals: 2
realStepSize: 0.01
width: 100
height: 30
colorScheme: hifi.colorSchemes.light
onFocusChanged: {
if(focus) {
introspector.object = this
}
}
}
}
}
Item {
id: otherTab
}
}
}

View file

@ -0,0 +1,166 @@
import QtQuick 2.1;
import QtQuick.Window 2.1;
MouseArea {
id: base;
opacity: 0.65;
// anchors.fill: parent;
width: 400;
height: 300;
drag.target: list;
onWheel: { }
onClicked: { object = null }
property var object: null
onObjectChanged: {
visible = (object != null)
}
property var properties: []
onPropertiesChanged: {
console.debug('properties: ', JSON.stringify(properties, 4, 0))
}
function getPropertiesList(obj) {
var props = [];
var propertiesObject = obj;
if(properties.length !== 0) {
propertiesObject = {};
for(var i = 0; i < properties.length; ++i) {
propertiesObject[properties[i]] = properties[i];
}
}
for(var prop in propertiesObject) {
var info = {'name' : prop};
var value = obj[prop];
var typeOfValue = typeof(value);
if(typeof(value) === 'string') {
info['type'] = 'string'
} else if(typeof(value) === 'number') {
if(Number.isInteger(value))
info['type'] = 'int'
else
info['type'] = 'float'
} else if(typeof(value) === 'boolean') {
info['type'] = 'boolean'
} else if(typeof(value) === 'function') {
continue;
}
/*
if(prop !== 'parent' && prop !== 'data' && prop !== 'children')
console.debug('typeof(value): ', typeof(value), JSON.stringify(value, null, 4));
*/
info['subName'] = ''
props.push(info);
}
return props;
}
Rectangle {
color: "lightgray";
anchors.fill: list;
anchors.margins: -50;
}
ListView {
id: list;
x: 50;
y: 50;
width: 400;
height: 300;
spacing: 5;
model: object !== null ? getPropertiesList(object) : [];
header: Text {
text: object !== null ? object.toString () : '';
font.bold: true;
font.pixelSize: 20;
}
delegate: Row {
spacing: 20;
Column {
width: 180;
Text {
text: (modelData ["subName"] !== "" ? (modelData ["name"] + "." + modelData ["subName"]) : modelData ["name"]);
font.pixelSize: 16;
}
}
Column {
width: 200;
Text {
text: {
return modelData ["type"]
}
font.pixelSize: 10;
}
TextInput {
id: input;
text: display;
width: parent.width;
font.pixelSize: 16;
font.underline: (text !== display);
Keys.onReturnPressed: { save (); }
Keys.onEnterPressed: { save (); }
Keys.onEscapePressed: { cancel (); }
property string display : "";
function save () {
var tmp;
switch (modelData ["type"]) {
case 'boolean':
tmp = (text === "true" || text === "1");
break;
case 'float':
tmp = parseFloat (text);
break;
case 'int':
tmp = parseInt (text);
break;
case 'string':
tmp = text;
break;
default:
break;
}
if (modelData ["subName"] !== "") {
object [modelData ["name"]][modelData ["subName"]] = tmp;
}
else {
object [modelData ["name"]] = tmp;
}
text = display;
}
function cancel () {
text = display;
}
Binding on text { value: input.display; }
Binding on display {
value: {
var ret = (modelData ["subName"] !== ""
? object [modelData ["name"]][modelData ["subName"]]
: object [modelData ["name"]]);
return ret.toString ();
}
}
Rectangle {
z: -1;
color: "white";
anchors.fill: parent;
}
}
}
}
}
}

View file

@ -0,0 +1,23 @@
(function() { // BEGIN LOCAL_SCOPE
console.debug('controlsGallery: creating window')
var qml = Script.resolvePath('ControlsGallery.qml');
var qmlWindow = new OverlayWindow({
title: 'Hifi Controls Gallery',
source: qml,
height: 480,
width: 640,
visible: true
});
console.debug('controlsGallery: creating window... done')
qmlWindow.closed.connect(function() { Script.stop(); });
Script.scriptEnding.connect(function() {
console.debug('controlsGallery: end of scripting')
delete qmlWindow;
});
}()); // END LOCAL_SCOPE

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -16,9 +16,11 @@
(function() { // BEGIN LOCAL_SCOPE
var EMOTE_ANIMATIONS = ['Crying', 'Surprised', 'Dancing', 'Cheering', 'Waving', 'Fall', 'Pointing', 'Clapping'];
var EMOTE_ANIMATIONS = ['Cry', 'Surprised', 'Dance', 'Cheer', 'Wave', 'Fall', 'Point', 'Clap', 'Sit1', 'Sit2', 'Sit3', 'Love'];
var ANIMATIONS = Array();
var eventMappingName = "io.highfidelity.away"; // restoreAnimation on hand controller button events, too
var eventMapping = Controller.newMapping(eventMappingName);
EMOTE_ANIMATIONS.forEach(function (name) {
var animationURL = Script.resolvePath("assets/animations/" + name + ".fbx");
@ -31,16 +33,15 @@ EMOTE_ANIMATIONS.forEach(function (name) {
var EMOTE_APP_BASE = "html/EmoteApp.html";
var EMOTE_APP_URL = Script.resolvePath(EMOTE_APP_BASE);
var EMOTE_LABEL = "EMOTE";
var EMOTE_APP_SORT_ORDER = 11;
var EMOTE_APP_SORT_ORDER = 12;
var FPS = 60;
var MSEC_PER_SEC = 1000;
var FINISHED = 3; // see ScriptableResource::State
var onEmoteScreen = false;
var button;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var activeTimer = false; // used to cancel active timer if a user plays an amimation while another animation is playing
var activeEmote = false; // to keep track of the currently playing emote
var activeTimer = false; // Used to cancel active timer if a user plays an animation while another animation is playing
var activeEmote = false; // To keep track of the currently playing emote
button = tablet.addButton({
icon: "icons/tablet-icons/EmoteAppIcon.svg",
@ -58,7 +59,7 @@ function onClicked() {
}
function onScreenChanged(type, url) {
onEmoteScreen = type === "Web" && (url.indexOf(EMOTE_APP_BASE) == url.length - EMOTE_APP_BASE.length);
onEmoteScreen = type === "Web" && (url.indexOf(EMOTE_APP_BASE) === url.length - EMOTE_APP_BASE.length);
button.editProperties({ isActive: onEmoteScreen });
}
@ -71,34 +72,79 @@ function onWebEventReceived(event) {
}
if (event.type === "click") {
var emoteName = event.data;
if (ANIMATIONS[emoteName].resource.state == FINISHED) {
if (activeTimer !== false) {
Script.clearTimeout(activeTimer);
if (activeTimer !== false) {
Script.clearTimeout(activeTimer);
}
// If the activeEmote is different from the chosen emote, then play the new emote. Other wise,
// This is a second click on the same emote as the activeEmote, and we will just stop it.
if (activeEmote !== emoteName) {
activeEmote = emoteName;
// Allow for a random sitting animation when a user selects sit
var randSit = Math.floor(Math.random() * 3) + 1;
if (emoteName === "Sit"){
emoteName = event.data + randSit; // "Sit1, Sit2, Sit3"
}
// if the activeEmote is different from the chosen emote, then play the new emote. Other wise,
// this is a second click on the same emote as the activeEmote, and we will just stop it.
if (activeEmote !== emoteName) {
activeEmote = emoteName;
var frameCount = ANIMATIONS[emoteName].animation.frames.length;
var frameCount = ANIMATIONS[emoteName].animation.frames.length;
// Three types of emotes (non-looping end, non-looping return, looping)
if (emoteName.match(/^Sit.*$/) || emoteName === "Fall") { // non-looping end
MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount);
// Non-looping return
} else if (emoteName === "Love" || emoteName === "Surprised" || emoteName === "Cry" || emoteName === "Point"){
MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, false, 0, frameCount);
var timeOut = MSEC_PER_SEC * frameCount / FPS;
activeTimer = Script.setTimeout(function () {
MyAvatar.restoreAnimation();
activeTimer = false;
activeEmote = false;
}, timeOut);
} else {
activeEmote = false;
MyAvatar.restoreAnimation();
} else { // Looping
MyAvatar.overrideAnimation(ANIMATIONS[emoteName].url, FPS, true, 0, frameCount);
}
} else {
activeEmote = false;
MyAvatar.restoreAnimation();
}
}
}
// If a user provides input, end the emote animation and restore the navigation animation states (idle, walk, run)
function restoreAnimation() {
MyAvatar.restoreAnimation();
}
Controller.keyPressEvent.connect(restoreAnimation);
// Note peek() so as to not interfere with other mappings.
eventMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.LB).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.LS).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.LeftGrip).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.RB).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.RS).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.RightGrip).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.Back).peek().to(restoreAnimation);
eventMapping.from(Controller.Standard.Start).peek().to(restoreAnimation);
Controller.enableMapping(eventMappingName);
button.clicked.connect(onClicked);
tablet.screenChanged.connect(onScreenChanged);
tablet.webEventReceived.connect(onWebEventReceived);

View file

@ -38,7 +38,7 @@
.content {
margin-top: 90px;
padding: 30px;
padding: 10px 30px;
}
input[type=button] {
@ -47,9 +47,9 @@
font-size: 20px;
text-transform: uppercase;
vertical-align: top;
height: 105px;
height: 90px;
min-width: 190px;
padding: 0px 18px;
padding: 0px 10px;
margin-right: 6px;
border-radius: 5px;
border: none;
@ -97,15 +97,17 @@
<h4>Emote App</h4>
</div>
<div class="content">
<p>Click an emotion to Emote:<p>
<p><input type="button" class="emote-button white" value="Crying">
<p>Choose an emote:<p>
<p><input type="button" class="emote-button white" value="Cry">
<input type="button" class="emote-button white" value="Surprised"></p>
<p><input type="button" class="emote-button white" value="Dancing">
<input type="button" class="emote-button white" value="Cheering"></p>
<p><input type="button" class="emote-button white" value="Waving">
<p><input type="button" class="emote-button white" value="Dance">
<input type="button" class="emote-button white" value="Cheer"></p>
<p><input type="button" class="emote-button white" value="Wave">
<input type="button" class="emote-button white" value="Fall"></p>
<p><input type="button" class="emote-button white" value="Pointing">
<input type="button" class="emote-button white" value="Clapping"></p>
<p><input type="button" class="emote-button white" value="Point">
<input type="button" class="emote-button white" value="Clap"></p>
<p><input type="button" class="emote-button white" value="Sit">
<input type="button" class="emote-button white" value="Love"></p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

View file

@ -15,6 +15,7 @@ Script.include(Script.resolvePath("../libraries/controllers.js"));
Script.include(Script.resolvePath("../libraries/Xform.js"));
var Y_AXIS = {x: 0, y: 1, z: 0};
var X_AXIS = {x: 1, y: 0, z: 0};
var DEFAULT_DPI = 31;
var DEFAULT_WIDTH = 0.4375;
var DEFAULT_VERTICAL_FIELD_OF_VIEW = 45; // degrees
@ -33,10 +34,16 @@ var DELAY_FOR_30HZ = 33; // milliseconds
// will need to be recaclulated if dimensions of fbx model change.
var TABLET_NATURAL_DIMENSIONS = {x: 32.083, y: 48.553, z: 2.269};
var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-close.png";
var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "images/button-close.png";
// var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-close.png";
// var TABLET_MODEL_PATH = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx";
var LOCAL_BEZEL_HIGHLIGHT = Script.resourcesPath() + "images/buttonBezel_highlight.png";
var LOCAL_NORMAL_BEZEL = Script.resourcesPath() + "images/buttonBezel.png";
var LOCAL_TABLET_MODEL_PATH = Script.resourcesPath() + "meshes/tablet-with-home-button-small-bezel.fbx";
var HIGH_PRIORITY = 1;
var LOW_PRIORITY = 0;
var SUBMESH = 2;
// returns object with two fields:
// * position - position in front of the user
@ -134,11 +141,10 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
Overlays.deleteOverlay(this.webOverlayID);
}
var RAYPICK_OFFSET = 0.0007; // Sufficient for raypick to reliably intersect tablet screen before tablet model.
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.0) / sensorScaleFactor + RAYPICK_OFFSET;
var WEB_ENTITY_Y_OFFSET = 1 * tabletScaleFactor;
var screenWidth = 0.9275 * tabletWidth;
var screenHeight = 0.8983 * tabletHeight;
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.5) * sensorScaleFactor;
var WEB_ENTITY_Y_OFFSET = 1.25 * tabletScaleFactor;
var screenWidth = 0.9367 * tabletWidth;
var screenHeight = 0.9000 * tabletHeight;
this.webOverlayID = Overlays.addOverlay("web3d", {
name: "WebTablet Web",
url: url,
@ -154,12 +160,14 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
visible: visible
});
var HOME_BUTTON_Y_OFFSET = (tabletHeight / 2) - (tabletHeight / 20) + 0.003 * sensorScaleFactor;
// FIXME: Circle3D overlays currently at the wrong dimensions, so we need to account for that here
var homeButtonDim = 4.0 * tabletScaleFactor / 3.0;
var HOME_BUTTON_X_OFFSET = 0.00079 * sensorScaleFactor;
var HOME_BUTTON_Y_OFFSET = -1 * ((tabletHeight / 2) - (4.0 * tabletScaleFactor / 2));
var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleFactor;
this.homeButtonID = Overlays.addOverlay("circle3d", {
name: "homeButton",
localPosition: { x: 0.0, y: -HOME_BUTTON_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
localRotation: { x: 0, y: 1, z: 0, w: 0},
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim },
solid: true,
@ -170,24 +178,46 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
parentJointIndex: -1
});
this.homeButtonHighlightID = Overlays.addOverlay("circle3d", {
name: "homeButtonHighlight",
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
localRotation: { x: 0, y: 1, z: 0, w: 0 },
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim },
color: { red: 255, green: 255, blue: 255 },
solid: true,
innerRadius: 0.9,
ignoreIntersection: true,
alpha: 1.0,
visible: visible,
drawInFront: false,
parentID: this.tabletEntityID,
parentJointIndex: -1
});
this.homeButtonUnhighlightMaterial = Entities.addEntity({
type: "Material",
materialURL: "materialData",
localPosition: { x: 0.0, y: 0.0, z: 0.0 },
priority: HIGH_PRIORITY,
materialData: JSON.stringify({
materials: {
albedoMap: LOCAL_NORMAL_BEZEL
}
}),
userData: JSON.stringify({
"grabbableKey": {"grabbable": false}
}),
visible: false,
parentMaterialName: SUBMESH,
parentID: this.tabletEntityID
}, true);
this.homeButtonHighlightMaterial = Entities.addEntity({
type: "Material",
materialURL: "materialData",
localPosition: { x: 0.0, y: 0.0, z: 0.0 },
priority: LOW_PRIORITY,
visible: false,
materialData: JSON.stringify({
materials: {
emissiveMap: LOCAL_BEZEL_HIGHLIGHT
}
}),
userData: JSON.stringify({
"grabbableKey": {"grabbable": false}
}),
parentMaterialName: SUBMESH,
parentID: this.tabletEntityID
}, true);
this.receive = function (channel, senderID, senderUUID, localOnly) {
if (_this.homeButtonID == senderID) {
if (_this.homeButtonID === senderID) {
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var onHomeScreen = tablet.onHomeScreen();
var isMessageOpen;
@ -339,7 +369,8 @@ WebTablet.prototype.destroy = function () {
Overlays.deleteOverlay(this.webOverlayID);
Overlays.deleteOverlay(this.tabletEntityID);
Overlays.deleteOverlay(this.homeButtonID);
Overlays.deleteOverlay(this.homeButtonHighlightID);
Entities.deleteEntity(this.homeButtonUnhighlightMaterial);
Entities.deleteEntity(this.homeButtonHighlightMaterial);
HMD.displayModeChanged.disconnect(this.myOnHmdChanged);
Controller.mousePressEvent.disconnect(this.myMousePressEvent);
@ -433,21 +464,24 @@ WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos
WebTablet.prototype.onHoverEnterOverlay = function (overlayID, pointerEvent) {
if (overlayID === this.homeButtonID) {
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 1.0 });
Entities.editEntity(this.homeButtonUnhighlightMaterial, {priority: LOW_PRIORITY});
Entities.editEntity(this.homeButtonHighlightMaterial, {priority: HIGH_PRIORITY});
}
}
};
WebTablet.prototype.onHoverOverOverlay = function (overlayID, pointerEvent) {
if (overlayID !== this.homeButtonID) {
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 });
Entities.editEntity(this.homeButtonUnhighlightMaterial, {priority: HIGH_PRIORITY});
Entities.editEntity(this.homeButtonHighlightMaterial, {priority: LOW_PRIORITY});
}
}
};
WebTablet.prototype.onHoverLeaveOverlay = function (overlayID, pointerEvent) {
if (overlayID === this.homeButtonID) {
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 });
Entities.editEntity(this.homeButtonUnhighlightMaterial, {priority: HIGH_PRIORITY});
Entities.editEntity(this.homeButtonHighlightMaterial, {priority: LOW_PRIORITY});
}
}
};
// compute position, rotation & parentJointIndex of the tablet
WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMouse, tabletProperties) {
@ -575,22 +609,6 @@ WebTablet.prototype.scheduleMouseMoveProcessor = function() {
}
};
WebTablet.prototype.handleHomeButtonHover = function(x, y) {
var pickRay = Camera.computePickRay(x, y);
var entityPickResults;
var homebuttonHovered = false;
entityPickResults = Overlays.findRayIntersection(pickRay, true, [this.tabletEntityID]);
if (entityPickResults.intersects && (entityPickResults.entityID === this.tabletEntityID ||
entityPickResults.overlayID === this.tabletEntityID)) {
var overlayPickResults = Overlays.findRayIntersection(pickRay, true, [this.homeButtonID], []);
if (overlayPickResults.intersects && overlayPickResults.overlayID === this.homeButtonID) {
homebuttonHovered = true;
}
}
Overlays.editOverlay(this.homeButtonHighlightID, { alpha: homebuttonHovered ? 1.0 : 0.0 });
}
WebTablet.prototype.mouseMoveEvent = function (event) {
if (this.dragging) {
this.currentMouse = {
@ -598,8 +616,6 @@ WebTablet.prototype.mouseMoveEvent = function (event) {
y: event.y
};
this.scheduleMouseMoveProcessor();
} else {
this.handleHomeButtonHover(event.x, event.y);
}
};
@ -626,8 +642,6 @@ WebTablet.prototype.mouseMoveProcessor = function () {
});
}
this.scheduleMouseMoveProcessor();
} else {
this.handleHomeButtonHover(this.currentMouse.x, this.currentMouse.y);
}
};

View file

@ -129,7 +129,8 @@ DISPATCHER_PROPERTIES = [
"userData",
"type",
"href",
"cloneable"
"cloneable",
"cloneDynamic"
];
// priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step

View file

@ -32,7 +32,7 @@ if (!Function.prototype.bind) {
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
@ -370,7 +370,7 @@ getTabletWidthFromSettings = function () {
resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride) {
if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID || !HMD.homeButtonHighlightID) {
if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID) {
return;
}
var sensorScaleFactor = sensorToWorldScaleOverride || MyAvatar.sensorToWorldScale;
@ -381,6 +381,7 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
sensorScaleOffsetOverride = 1 / sensorScaleFactor;
}
// will need to be recaclulated if dimensions of fbx model change.
var TABLET_NATURAL_DIMENSIONS = {x: 32.083, y: 48.553, z: 2.269};
var DEFAULT_DPI = 31;
@ -399,32 +400,26 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
});
// update webOverlay
var RAYPICK_OFFSET = 0.0007; // Sufficient for raypick to reliably intersect tablet screen before tablet model.
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.0) * sensorScaleOffsetOverride + RAYPICK_OFFSET;
var WEB_ENTITY_Y_OFFSET = 1 * tabletScaleFactor;
print(WEB_ENTITY_Y_OFFSET);
var screenWidth = 0.9275 * tabletWidth;
var screenHeight = 0.8983 * tabletHeight;
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.5) * sensorScaleOffsetOverride;
var WEB_ENTITY_Y_OFFSET = 1.25 * tabletScaleFactor * sensorScaleOffsetOverride;
var screenWidth = 0.9367 * tabletWidth;
var screenHeight = 0.9000 * tabletHeight;
var landscape = Tablet.getTablet("com.highfidelity.interface.tablet.system").landscape;
Overlays.editOverlay(HMD.tabletScreenID, {
localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET},
dimensions: {x: landscape ? screenHeight : screenWidth, y: landscape ? screenWidth : screenHeight, z: 0.1},
dpi: tabletDpi
});
// update homeButton
var HOME_BUTTON_Y_OFFSET = ((tabletHeight / 2) - (tabletHeight / 20) + 0.003 * sensorScaleFactor) * sensorScaleOffsetOverride;
// FIXME: Circle3D overlays currently at the wrong dimensions, so we need to account for that here
var homeButtonDim = 4.0 * tabletScaleFactor / 3.0;
var HOME_BUTTON_X_OFFSET = 0.00079 * sensorScaleOffsetOverride * sensorScaleFactor;
var HOME_BUTTON_Y_OFFSET = -1 * ((tabletHeight / 2) - (4.0 * tabletScaleFactor / 2)) * sensorScaleOffsetOverride;
var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride;
Overlays.editOverlay(HMD.homeButtonID, {
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
localRotation: Quat.angleAxis(180, Vec3.UNIT_Y),
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
});
Overlays.editOverlay(HMD.homeButtonHighlightID, {
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
localRotation: Quat.angleAxis(180, Vec3.UNIT_Y),
localPosition: { x: HOME_BUTTON_X_OFFSET, y: HOME_BUTTON_Y_OFFSET, z: -HOME_BUTTON_Z_OFFSET },
localRotation: { x: 0, y: 1, z: 0, w: 0 },
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
});
};

View file

@ -114,7 +114,6 @@ var selectionDisplay = null; // for gridTool.js to ignore
Overlays.editOverlay(HMD.tabletID, { isVisibleInSecondaryCamera : visibleInSecondaryCam });
Overlays.editOverlay(HMD.homeButtonID, { isVisibleInSecondaryCamera : visibleInSecondaryCam });
Overlays.editOverlay(HMD.homeButtonHighlightIDtabletID, { isVisibleInSecondaryCamera : visibleInSecondaryCam });
Overlays.editOverlay(HMD.tabletScreenID, { isVisibleInSecondaryCamera : visibleInSecondaryCam });
}

View file

@ -24,7 +24,7 @@
var validCheckTime = Date.now();
var debugTablet = false;
var tabletScalePercentage = 70.0;
UIWebTablet = null;
var UIWebTablet = null;
var MSECS_PER_SEC = 1000.0;
var MUTE_MICROPHONE_MENU_ITEM = "Mute Microphone";
var gTablet = null;
@ -103,8 +103,9 @@
UIWebTablet.register();
HMD.tabletID = UIWebTablet.tabletEntityID;
HMD.homeButtonID = UIWebTablet.homeButtonID;
HMD.homeButtonHighlightID = UIWebTablet.homeButtonHighlightID;
HMD.tabletScreenID = UIWebTablet.webOverlayID;
HMD.homeButtonHighlightMaterialID = UIWebTablet.homeButtonHighlightMaterial;
HMD.homeButtonUnhighlightMaterialID = UIWebTablet.homeButtonUnhighlightMaterial;
HMD.displayModeChanged.connect(onHmdChanged);
MyAvatar.sensorToWorldScaleChanged.connect(onSensorToWorldScaleChanged);
@ -130,7 +131,6 @@
tabletProperties.visible = true;
Overlays.editOverlay(HMD.tabletID, tabletProperties);
Overlays.editOverlay(HMD.homeButtonID, { visible: true });
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: true });
Overlays.editOverlay(HMD.tabletScreenID, { visible: true });
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 90 });
updateTabletWidthFromSettings(true);
@ -151,7 +151,6 @@
Overlays.editOverlay(HMD.tabletID, { visible: false });
Overlays.editOverlay(HMD.homeButtonID, { visible: false });
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: false });
Overlays.editOverlay(HMD.tabletScreenID, { visible: false });
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 1 });
}
@ -172,7 +171,6 @@
UIWebTablet = null;
HMD.tabletID = null;
HMD.homeButtonID = null;
HMD.homeButtonHighlightID = null;
HMD.tabletScreenID = null;
} else if (debugTablet) {
print("TABLET closeTabletUI, UIWebTablet is null");
@ -325,7 +323,8 @@
Overlays.deleteOverlay(tabletID);
HMD.tabletID = null;
HMD.homeButtonID = null;
HMD.homeButtonHighlightID = null;
HMD.tabletScreenID = null;
HMD.homeButtonHighlightMaterialID = null;
HMD.homeButtonUnhighlightMaterialID = null;
});
}()); // END LOCAL_SCOPE

View file

@ -27,7 +27,7 @@
"cheerio": "^0.19.0",
"electron-log": "1.1.1",
"extend": "^3.0.0",
"fs-extra": "^1.0.0",
"fs-extra": "^6.0.0",
"node-notifier": "^5.2.1",
"os-homedir": "^1.0.1",
"request": "^2.85.0",

View file

@ -115,17 +115,43 @@ const UPDATER_LOCK_FULL_PATH = getRootHifiDataDirectory() + "/" + UPDATER_LOCK_F
// Configure log
global.log = require('electron-log');
const logFile = getApplicationDataDirectory(true) + '/log.txt';
const oldLogFile = path.join(getApplicationDataDirectory(), '/log.txt');
const logFile = path.join(getApplicationDataDirectory(true), '/log.txt');
if (oldLogFile != logFile && fs.existsSync(oldLogFile)) {
if (!fs.existsSync(oldLogFile)) {
fs.moveSync(oldLogFile, logFile);
} else {
fs.remove(oldLogFile);
}
}
fs.ensureFileSync(logFile); // Ensure file exists
log.transports.file.maxSize = 5 * 1024 * 1024;
log.transports.file.file = logFile;
log.debug("build info", buildInfo);
log.debug("Root hifi directory is: ", getRootHifiDataDirectory());
log.debug("App Data directory:", getApplicationDataDirectory());
fs.ensureDirSync(getApplicationDataDirectory());
var oldLogPath = path.join(getApplicationDataDirectory(), '/logs');
var logPath = path.join(getApplicationDataDirectory(true), '/logs');
if (oldLogPath != logPath && fs.existsSync(oldLogPath)) {
if (!fs.existsSync(oldLogPath)) {
fs.moveSync(oldLogPath, logPath);
} else {
fs.remove(oldLogPath);
}
}
fs.ensureDirSync(logPath);
log.debug("Log directory:", logPath);
const configPath = path.join(getApplicationDataDirectory(), 'config.json');
var userConfig = new Config();
userConfig.load(configPath);
const ipcMain = electron.ipcMain;
var isShuttingDown = false;
function shutdown() {
log.debug("Normal shutdown (isShuttingDown: " + isShuttingDown + ")");
@ -232,27 +258,6 @@ function deleteOldFiles(directoryPath, maxAgeInSeconds, filenameRegex) {
}
}
var oldLogPath = path.join(getApplicationDataDirectory(), '/logs');
var logPath = path.join(getApplicationDataDirectory(true), '/logs');
if (oldLogPath != logPath) {
console.log("Migrating old logs from " + oldLogPath + " to " + logPath);
fs.copy(oldLogPath, logPath, err => {
if (err) {
console.error(err);
} else {
console.log('success!');
}
})
}
log.debug("Log directory:", logPath);
log.debug("Data directory:", getRootHifiDataDirectory());
const configPath = path.join(getApplicationDataDirectory(), 'config.json');
var userConfig = new Config();
userConfig.load(configPath);
// print out uncaught exceptions in the console
process.on('uncaughtException', function(err) {
log.error(err);

View file

@ -1 +1,2 @@
out
out

View file

@ -8,7 +8,7 @@ set(JSDOC_WORKING_DIR ${CMAKE_SOURCE_DIR}/tools/jsdoc)
file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/node_modules/.bin/jsdoc JSDOC_PATH)
file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/config.json JSDOC_CONFIG_PATH)
file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/out OUTPUT_DIR)
file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR} NATIVE_JSDOC_WORKING_DIR)
file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/root.js NATIVE_JSDOC_WORKING_DIR)
add_custom_command(TARGET ${TARGET_NAME}
COMMAND ${NPM_EXECUTABLE} --no-progress install && ${JSDOC_PATH} ${NATIVE_JSDOC_WORKING_DIR} -c ${JSDOC_CONFIG_PATH} -d ${OUTPUT_DIR}

View file

@ -2,12 +2,27 @@
##Prerequisites
* Install node.js
* Install node.js.
* Install jsdoc via npm. `npm install jsdoc -g`
If you would like the extra functionality for gravPrep:
* Run npm install
To generate html documentation for the High Fidelity JavaScript API:
* `cd tools/jsdoc`
* `jsdoc . -c config.json`
The out folder should contain index.html.
To generate the grav automation files, run node gravPrep.js after you have made a JSdoc output folder.
This will create files that are needed for hifi-grav and hifi-grav-content repos
The md files for hifi-grav-content are located in out/grav/06.api-reference.
The template twig html files for hifi-grav are located out/grav/templates.
if you would like to copy these to a local version of the docs on your system you can run with the follows args:
* node grav true "path/to/grav/" "path/to/grav/content"

671
tools/jsdoc/gravPrep.js Normal file
View file

@ -0,0 +1,671 @@
// Dependencies
const htmlclean = require('htmlclean');
const fs = require('fs');
const path = require('path');
const pretty = require('pretty');
const cheerio = require('cheerio');
const rimraf = require('rimraf');
const dedent = require('dedent-js');
// Arg Vars
const copyLocal = process.argv[2];
console.log("copyLocal:", copyLocal);
let targetTemplateDirectory = '';
let targetMDDirectory = '';
if (copyLocal) {
targetTemplateDirectory = process.argv[3];
targetMDDirectory = process.argv[4];;
}
// Required directories
let dir_out = path.join(__dirname, 'out');
let dir_grav = path.join(dir_out, 'grav');
let dir_css = path.join(dir_grav, 'css');
let dir_js = path.join(dir_grav, 'js');
let dir_template = path.join(dir_grav, 'templates');
let dir_md = path.join(dir_grav, '06.api-reference');
let dir_md_objects = path.join(dir_md, '02.Objects');
let dir_md_namespaces = path.join(dir_md, '01.Namespaces');
let dir_md_globals = path.join(dir_md, '03.Globals');
// Array to itterate over and create if doesn't exist
let dirArray = [dir_grav, dir_css, dir_js, dir_template, dir_md, dir_md_objects, dir_md_namespaces, dir_md_globals];
// Base Grouping Directories for MD files
let baseMDDirectories = ["API-Reference", "Globals", "Namespaces", "Objects"];
// Maps for directory names
let map_dir_md = {
"API-Reference": dir_md,
"Globals": dir_md_globals,
"Objects": dir_md_objects,
"Namespaces": dir_md_namespaces,
"Class": dir_md_objects,
"Namespace": dir_md_namespaces,
"Global": dir_md_globals
}
// Map for Links
let map_links = {
"Global": "globals",
"Namespace": "namespaces",
"Class": "objects"
}
// Mapping for GroupNames and Members
let groupNameMemberMap = {
"Objects": [],
"Namespaces": [],
"Globals": []
}
// Html variables to be handle regex replacements
const html_reg_static = /<span class="type-signature">\(static\)<\/span>/g
const html_reg_title = /\<h1.+?\>.+?\<\/h1\>/g;
const html_reg_htmlExt = /\.html/g;
const html_reg_objectHeader = /<header>[\s\S]+?<\/header>/;
const html_reg_objectSpanNew = /<h5 class="name"[\s\S]+?<\/span><\/h5>/;
const html_reg_propertiesHeaderEdit = '<h4 class="subsection-title">Properties:</h4>';
const html_reg_propertiesHeaderEdit_Replace = '<h4 class="subsection-title">Properties</h4>';
const html_reg_typeEdit = /(<h5>Returns[\s\S]*?Type)(<\/dt[\s\S]*?type">)(.*?)(<\/span><\/dd>[\s\S]*?<\/dl>)/g;
const html_reg_typeEdit_replace = '$1: $3</dt></dl>'
const html_reg_methodSize = /(<h4)( class="name"[\s\S]*?)(<\/h4>)/g;
const html_reg_methodSize_replace = '<h5$2</h5>';
const html_reg_findByName = '<h5 class="name"';
const html_reg_findByTitle = '<h1>';
const html_reg_findByMethod = '<h3 class="subsection-title">Methods</h3>'
const html_reg_findByMethod_replace = '<h4 class="subsection-title">Methods</h4>'
const html_reg_findByArticleClose = `</article>`
const html_reg_signalTitle = `<h4 class="subsection-title">Signals</h4>`;
const html_reg_typeDefinitonsTitle = /<h3 class="subsection-title">Type Definitions<\/h3>/;
const html_reg_typeDefinitonsTitle_replace = `<h4 class="subsection-title">Type Definitions</h4>`
const html_reg_classDefinitonsTitle = /<h3 class="subsection-title">Classes<\/h3>/;
const html_reg_classDefinitonsTitle_replace = `<h4 class="subsection-title">Classes</h4>`
const html_reg_firstDivClose = `</div>`;
const html_reg_allNonHTTPLinks = /(<a href=")(?!http)([\s\S]+?)(">)/g;
const html_reg_allHTTPLinks = /(<a href=")(http)([\s\S]+?)(">)/g;
const html_reg_pretty = /(<pre class="prettyprint">)([\s\S]*?)(<\/pre>)/g;
const html_reg_pretty_replace = "<pre>$2<\/pre>";
const html_reg_availableIn = /(<table>[\s\S]+?Available in:[\s\S]+?<\/table>)/g;
const html_reg_findControllerCuratedList = /<h5>Functions<\/h5>[\s\S]*?<p>Input Recordings[\s\S]*?<\/ul>/g
const html_reg_findEntityMethods = /<h5>Entity Methods:[\s\S]+?<\/ul>/g;
const html_reg_EntityMethodsHeader = '<h5>Entity Methods:</h5>';
const html_reg_EntityMethodsHeader_replace = '<h5>Entity Methods</h5>';
const html_reg_dlClassDetails = /<dl class="details"><\/dl>/g
const html_reg_typeDefType = /(<h5>)(Type:)(<\/h5>[\s\S]*?)(<span[\s\S]*?)(<\/li>[\s\S]*?<\/ul>)/g;
const html_reg_typeDefType_replace = `<dl><dt>$2 $4</dl></dt>`;
const html_reg_returnSize = /<h5>Returns:<\/h5>/g;
const html_reg_returnSize_replace = '<h6>Returns:<\/h6>';
const html_reg_depreciated = /(<dt class="important tag-deprecated"[\s\S]+?<\/dt>[\s\S]+?)(<dd>)([\s\S]+?<ul[\s\S]+?<li>)([\s\S]+?)(<\/ul>[\s\S]+?)(<\/dd>)/g;
const html_reg_depreciated_replace = '<em><strong>$1</strong><div>$4</div></em>'
// Procedural functions
//remove .html from non http links
function removeHTML(match, p1, p2, p3) {
p2 = p2.replace(".html", "");
return [p1, p2, p3].join("");
}
// Turn links to lower case that aren't part of IDs
function allLinksToLowerCase(match, p1, p2, p3) {
// split on id # and make sure only the preceding is lower case
if (p2.indexOf("#") > -1) {
p2 = p2.split("#");
p2 = [p2[0].toLowerCase(), "#", p2[1]].join("");
} else {
p2 = p2.toLowerCase();
}
return [p1, p2, p3].join("");
}
// Helper for fixing formatting of page links
function fixLinkGrouping(match, p1, p2, p3) {
// Handle if referencing ID
let count = (p2.match(/\./g) || []).length;
if (p2.indexOf("#") > -1) {
let split = p2.split("#");
if (count >= 2) {
// console.log("MULTI DOTS!");
split = p2.split(".");
// This is a case where we are in an object page and there are multiple levels referenced (only doing 2 levels at the moment)
// console.log("split", split)
return [p1, "/api-reference/", returnRightGroup(split[1].slice(0, -1)), "/", split[1], ".", split[2], p3].join("");
}
if (split[0] === "global") {
return [p1, "/api-reference/", "globals", "#", split[1], p3].join("");
}
return [p1, "/api-reference/", returnRightGroup(split[0]), "/", p2, p3].join("");
} else {
// Handle if there are member references
// console.log("count", count)
let split;
if (count === 1) {
split = p2.split(".");
return [p1, "/api-reference/", returnRightGroup(split[1]), "/", split[1], p3].join("");
}
return [p1, "/api-reference/", returnRightGroup(p2), "/", p2, p3].join("");
}
}
// Return the right group for where the method or type came from
function returnRightGroup(methodToCheck) {
for (var key in groupNameMemberMap) {
for (i = 0; i < groupNameMemberMap[key].length; i++) {
if (methodToCheck.toLowerCase() === groupNameMemberMap[key][i].toLowerCase()) {
return key.toLowerCase();
} else {
// console.log("Couldn't find group: ", methodToCheck);
}
}
}
}
// Create the actual MD file
function createMD(title, directory, needsDir, isGlobal) {
let mdSource = makeMdSource(title);
if (needsDir) {
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory);
}
}
let destinationMDFile = path.join(directory, `API_${title}.md`);
fs.writeFileSync(destinationMDFile, mdSource);
}
// Create the actual Template file
function createTemplate(title, content) {
let twigBasePartial = makeTwigFile(content);
let destinationFile = path.join(dir_template, `API_${title}.html.twig`);
fs.writeFileSync(destinationFile, twigBasePartial);
}
// Copy file from source to target - used for recurssive call
function copyFileSync(source, target) {
let targetFile = target;
// If target is a directory a new file with the same name will be created
if (fs.existsSync(target)) {
if (fs.lstatSync(target).isDirectory()) {
targetFile = path.join(target, path.basename(source));
}
}
fs.writeFileSync(targetFile, fs.readFileSync(source));
}
// Copy file from source to target
function copyFolderRecursiveSync(source, target) {
var files = [];
// Check if folder needs to be created or integrated
var targetFolder = path.join(target, path.basename(source));
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder);
}
// Copy
if (fs.lstatSync(source).isDirectory()) {
files = fs.readdirSync(source);
files.forEach(function(file) {
var curSource = path.join(source, file);
if (fs.lstatSync(curSource).isDirectory()) {
copyFolderRecursiveSync(curSource, targetFolder);
} else {
copyFileSync(curSource, targetFolder);
}
});
}
}
// Clean up the Html
function prepareHtml(source) {
let htmlBefore = fs.readFileSync(source, { encoding: 'utf8' });
let htmlAfter = htmlclean(htmlBefore);
let htmlAfterPretty = pretty(htmlAfter);
return cheerio.load(htmlAfterPretty);
}
// Base file for MD's
function makeMdSource(title) {
return dedent(
`
---
title: ${title}
taxonomy:
category:
- docs
visible: true
highlight:
enabled: false
---
`
)
}
// Base file for Templates
function makeTwigFile(contentHtml) {
return dedent(
`
{% extends 'partials/base_noGit.html.twig' %}
{% set tags = page.taxonomy.tag %}
{% if tags %}
{% set progress = page.collection({'items':{'@taxonomy':{'category': 'docs', 'tag': tags}},'order': {'by': 'default', 'dir': 'asc'}}) %}
{% else %}
{% set progress = page.collection({'items':{'@taxonomy':{'category': 'docs'}},'order': {'by': 'default', 'dir': 'asc'}}) %}
{% endif %}
{% block navigation %}
<div id="navigation">
{% if not progress.isFirst(page.path) %}
<a class="nav nav-prev" href="{{ progress.nextSibling(page.path).url }}"> <img src="{{ url('theme://images/left-arrow.png') }}"></a>
{% endif %}
{% if not progress.isLast(page.path) %}
<a class="nav nav-next" href="{{ progress.prevSibling(page.path).url }}"><img src="{{ url('theme://images/right-arrow.png') }}"></a>
{% endif %}
</div>
{% endblock %}
{% block content %}
<div id="api-specific">
<div id="body-inner">
<h1>{{ page.title }}</h1>
${contentHtml}
</div>
</div>
{% endblock %}
`
)
}
// Handle NameSpace Group
function handleNamespace(title, content) {
let destinationDirectory = path.join(map_dir_md["Namespace"], title);
createMD(title, destinationDirectory, true);
createTemplate(title, content);
}
// Handle Class Group
function handleClass(title, content) {
let destinationDirectory = path.join(map_dir_md["Class"], title);
createMD(title, destinationDirectory, true)
let formatedHtml = content
.replace(html_reg_objectSpanNew, "")
createTemplate(title, formatedHtml);
}
// Handle Global Group
function handleGlobal(title, content) {
createMD("Globals", map_dir_md["Global"], false, true);
createTemplate("Globals", content);
}
// Handle Group TOCs
function makeGroupTOC(group) {
let mappedGroup;
if (!Array.isArray(group)) {
mappedGroup = groupNameMemberMap[group];
} else {
mappedGroup = group;
}
let htmlGroup = mappedGroup.map(item => {
return dedent(
`
<div>
<a href="/api-reference/${
!Array.isArray(group)
? `${group.toLowerCase()}/` + item.toLowerCase()
: item.toLowerCase()
}/">${item}</a>
</div>
`
)
})
return htmlGroup.join("\n");
}
// Handle Class TOCS
function makeClassTOC(group){
let linkArray = []
group.forEach( item => {
linkArray.push(`<div><h5>${item.type}</h5></div>`)
item.array.forEach( link => {
if ( link.indexOf('.') > -1 ){
linkArray.push(`<div><a href="#${link}">${link.slice(1)}</a></div>`);
} else {
linkArray.push(`<div><a href="#${link}">${link}</a></div>`);
}
})
linkArray.push("<br>");
})
return linkArray.join("\n");
}
// Extract IDS for TOC
function extractIDs(groupToExtract){
let firstLine = "";
let id = "";
let extractedIDs = [];
groupToExtract.forEach((item)=>{
firstLine = item.split("\n")[0];
try {
id = firstLine.split('id="')[1].split(`"`)[0];
} catch (e){
id = "";
}
if (id){
extractedIDs.push(id)
}
})
return extractedIDs;
}
// Helper for splitting up html
// Takes: Content to split, SearchTerm to Split by, and term to End Splitting By
// Returns: [newContent after Split, Array of extracted ]
function splitBy(content, searchTerm, endSplitTerm, title){
let foundArray = [];
let curIndex = -1;
let afterCurSearchIndex = -1
let nextIndex = 0;
let findbyNameLength = searchTerm.length;
let curEndSplitTermIndex = -1;
let classHeader;
do {
// Find the index of where to stop searching
curEndSplitTermIndex = content.indexOf(endSplitTerm);
// console.log("curEndSplitTermIndex", curEndSplitTermIndex)
// Find the index of the the next Search term
curIndex = content.indexOf(searchTerm);
// console.log("curIndex", curIndex)
// The index of where the next search will start
afterCurSearchIndex = curIndex+findbyNameLength;
// Find the content of the next Index
nextIndex = content.indexOf(searchTerm,afterCurSearchIndex);
// If the next index isn't found, then next index === index of the end term
if (nextIndex === -1){
nextIndex = curEndSplitTermIndex;
}
if (curIndex > curEndSplitTermIndex){
break;
}
// Push from the cur index to the next found || the end term
let contentSlice = content.slice(curIndex, nextIndex);
if (contentSlice.indexOf(`id="${title}"`) === -1){
foundArray.push(contentSlice);
} else {
classHeader = contentSlice;
}
// Remove that content
content = content.replace(contentSlice, "");
curEndSplitTermIndex = content.indexOf(endSplitTerm);
nextIndex = content.indexOf(searchTerm,afterCurSearchIndex);
// Handle if nextIndex goes beyond endSplitTerm
if (nextIndex > curEndSplitTermIndex) {
curIndex = content.indexOf(searchTerm);
contentSlice = content.slice(curIndex, curEndSplitTermIndex);
if (contentSlice.indexOf(`id="${title}"`) === -1){
foundArray.push(contentSlice);
}
content = content.replace(contentSlice, "");
break;
}
} while (curIndex > -1)
if (classHeader){
content = append(content, html_reg_findByArticleClose, classHeader, true);
}
return [content, foundArray];
}
// Split the signals and methods [Might make this more generic]
function splitMethodsSignals(allItemToSplit){
let methodArray = [];
let signalArray = [];
allItemToSplit.forEach( (content, index) => {
firstLine = content.split("\n")[0];
if (firstLine.indexOf("{Signal}") > -1){
signalArray.push(content);
} else if (firstLine.indexOf("span") > -1) {
methodArray.push(content);
} else {
}
})
return [methodArray, signalArray];
}
// Helper to append
// Takes content, the search term to appendTo, the content to append,
// and bool if the append is before the found area
function append(content, searchTermToAppendto, contentToAppend, appendBefore){
let contentArray = content.split("\n");
let foundIndex = findArrayTrim(contentArray, searchTermToAppendto)
foundIndex = appendBefore ? foundIndex : foundIndex +1
contentArray.splice(foundIndex,0,contentToAppend)
return contentArray.join("\n")
}
// Helper function for append
function findArrayTrim(array, searchTerm){
var index = -1;
for (var i = 0; i < array.length; i++){
index = array[i].trim().indexOf(searchTerm.trim());
if (index > -1){
return i
}
}
return index;
}
// Remove grav directory if exists to make sure old files aren't kept
if (fs.existsSync(dir_grav)){
console.log("dir_grav exists");
rimraf.sync(dir_grav);
}
// Create Grav directories in JSDOC output
dirArray.forEach(function(dir){
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
})
// Create baseMD files
baseMDDirectories.forEach( md => {
createMD(md, map_dir_md[md]);
})
// Read jsdoc output folder and process html files
let files = fs.readdirSync(dir_out);
// Create initial Group name member map to handle individual link
files.forEach(function (file){
let curSource = path.join(dir_out, file);
if (path.extname(curSource) == ".html" && path.basename(curSource, '.html') !== "index") {
let loadedHtml = prepareHtml(curSource);
let splitTitle = loadedHtml("title").text().split(": ");
let groupName = splitTitle[1];
let htmlTitle = splitTitle.pop();
switch(groupName){
case "Namespace":
groupNameMemberMap["Namespaces"].push(htmlTitle);
break;
case "Class":
groupNameMemberMap["Objects"].push(htmlTitle);
break;
default:
console.log(`Case not handled for ${groupName}`);
}
}
})
files.forEach(function (file, index){
// For testing individual files
// if (index !== 59) return;
let curSource = path.join(dir_out, file);
if (path.extname(curSource) == ".html" && path.basename(curSource, '.html') !== "index") {
// Clean up the html source
let loadedHtml = prepareHtml(curSource);
// Extract the title, group name, and the main div
let splitTitle = loadedHtml("title").text().split(": ");
let groupName = splitTitle[1];
let htmlTitle = splitTitle.pop();
console.log("html title", htmlTitle)
let mainDiv = loadedHtml("#main")
let methodIDs = [];
let signalIDs = [];
let typeDefIDs = [];
// Basic Regex HTML edits
let currentContent = mainDiv.html()
.replace(html_reg_findByMethod, "") //Remove Method title to be remade later
.replace(html_reg_static,"") // Remove static from the file names
.replace(html_reg_title,"") // Remove title
.replace(html_reg_objectHeader,"") // Remove extra Object Header
.replace(html_reg_dlClassDetails, "") // Remove unneccsary dlClassDetails Tag
.replace(html_reg_allNonHTTPLinks, removeHTML) // Remove the .html extension from all links
.replace(html_reg_allNonHTTPLinks, allLinksToLowerCase) // Turn all links into lowercase before ID tags
.replace(html_reg_allNonHTTPLinks, fixLinkGrouping) // Make sure links refer to correct grouping
.replace(html_reg_propertiesHeaderEdit, html_reg_propertiesHeaderEdit_Replace) // Remove : from Properties
.replace(html_reg_typeEdit, html_reg_typeEdit_replace) // Put type on the same line
.replace(html_reg_returnSize, html_reg_returnSize_replace) // Make return size h6 instead of h5
.replace(html_reg_methodSize, html_reg_methodSize_replace) // Make method size into h5
.replace(html_reg_pretty, html_reg_pretty_replace) // remove the references to pretty
.replace(html_reg_classDefinitonsTitle, html_reg_classDefinitonsTitle_replace) // Change the class def titles
.replace(html_reg_depreciated, html_reg_depreciated_replace); // format depreciated better
// Further HTML Manipulation
// Make end term either Type Definitions or by the article
let endTerm;
let foundTypeDefinitions;
let foundSignalsAndMethods;
if (currentContent.indexOf("Type Definitions") > -1){
// console.log("Found Type Definitions");
endTerm = `<h3 class="subsection-title">Type Definitions</h3>`;
// Split HTML by Each named entry
let contentSplitArray = splitBy(currentContent, html_reg_findByName, endTerm, htmlTitle);
foundSignalsAndMethods = contentSplitArray[1];
// console.log("foundSignalsAndMethods", foundSignalsAndMethods)
// Create a reference to the current content after split and the split functions
currentContent = contentSplitArray[0]
.replace(html_reg_typeDefType, html_reg_typeDefType_replace) // Edit how the typedef type looks
.replace(html_reg_typeDefinitonsTitle, ""); // Remove Type Definitions Title to be remade later;
endTerm = html_reg_findByArticleClose;
// Grab split Type Definitions
let contentSplitArrayForTypeDefs = splitBy(currentContent, html_reg_findByName, endTerm, htmlTitle);
currentContent = contentSplitArrayForTypeDefs[0];
foundTypeDefinitions = contentSplitArrayForTypeDefs[1];
// console.log("foundTypeDefinitions", foundTypeDefinitions)
} else {
endTerm = html_reg_findByArticleClose;
let contentSplitArray = splitBy(currentContent, html_reg_findByName, endTerm, htmlTitle);
foundSignalsAndMethods = contentSplitArray[1];
currentContent = contentSplitArray[0];
}
// Create references to the split methods and signals
let processedMethodsSignalsAndTypeDefs = splitMethodsSignals(foundSignalsAndMethods);
let splitMethods = processedMethodsSignalsAndTypeDefs[0];
let splitSignals = processedMethodsSignalsAndTypeDefs[1];
let splitTypeDefinitionIDS;
let splitMethodIDS = extractIDs(splitMethods);
let splitSignalIDS = extractIDs(splitSignals);
if (foundTypeDefinitions){
splitTypeDefinitionIDS = extractIDs(foundTypeDefinitions);
}
let arrayToPassToClassToc = [];
if (splitMethods.length > 0) {
arrayToPassToClassToc.push({type: "Methods", array: splitMethodIDS});
// Add the Methods header to the Methods HTML
splitMethods.unshift(html_reg_findByMethod_replace)
currentContent = append(currentContent, html_reg_findByArticleClose, splitMethods.join('\n'), true);
}
if (splitSignals.length > 0) {
arrayToPassToClassToc.push({type: "Signals", array: splitSignalIDS});
// Add the Signals header to the Signals HTML
splitSignals.unshift(html_reg_signalTitle)
currentContent = append(currentContent, html_reg_findByArticleClose, splitSignals.join('\n'),true);
}
if (foundTypeDefinitions && foundTypeDefinitions.length > 0) {
arrayToPassToClassToc.push({type: "Type Definitions", array: splitTypeDefinitionIDS});
// Add the Type Defs header to the Type Defs HTML
foundTypeDefinitions.unshift(html_reg_typeDefinitonsTitle_replace)
currentContent = append(currentContent, html_reg_findByArticleClose, foundTypeDefinitions.join('\n'), true);
}
let classTOC = makeClassTOC(arrayToPassToClassToc);
if (groupName === "Global"){
currentContent = append(currentContent, html_reg_findByTitle, classTOC);
} else if (htmlTitle === "Controller") {
let curatedList = currentContent.match(html_reg_findControllerCuratedList);
currentContent = currentContent.replace(html_reg_findControllerCuratedList, "");
let entityMethods = currentContent.match(html_reg_findEntityMethods);
currentContent = currentContent.replace(html_reg_findEntityMethods, "");
currentContent = append(currentContent, html_reg_firstDivClose, [classTOC, curatedList, entityMethods].join("\n"));
currentContent = currentContent.replace(html_reg_EntityMethodsHeader, html_reg_EntityMethodsHeader_replace);
} else {
currentContent = append(currentContent, html_reg_firstDivClose, classTOC);
}
// Final Pretty Content
currentContent = htmlclean(currentContent);
currentContent = pretty(currentContent);
// Handle Unique Categories
switch(groupName){
case "Namespace":
handleNamespace(htmlTitle, currentContent);
break;
case "Class":
handleClass(htmlTitle, currentContent);
break;
case "Global":
handleGlobal(htmlTitle, currentContent);
break;
default:
console.log(`Case not handled for ${groupName}`);
}
}
})
// Create the base Templates after processing individual files
createTemplate("API-Reference", makeGroupTOC(["Namespaces", "Objects", "Globals"]));
createTemplate("Namespaces", makeGroupTOC("Namespaces"));
createTemplate("Objects", makeGroupTOC("Objects"));
// Copy the files to the target Directories if Local
if (copyLocal){
// Copy files to the Twig Directory
let templateFiles = fs.readdirSync(path.resolve(targetTemplateDirectory));
// Remove Existing API files
templateFiles.forEach(function(file){
let curSource = path.join(targetTemplateDirectory, file);
if(path.basename(file, '.html').indexOf("API") > -1){
fs.unlink(curSource);
}
})
copyFolderRecursiveSync(dir_template, targetTemplateDirectory);
// Copy files to the Md Directory
let baseMdRefDir = path.join(targetMDDirectory,"06.api-reference");
// Remove existing MD directory
if (fs.existsSync(baseMdRefDir)){
rimraf.sync(baseMdRefDir);
}
copyFolderRecursiveSync(dir_md, targetMDDirectory);
}

View file

@ -1,7 +1,14 @@
{
"name": "hifiJSDoc",
"dependencies": {
"jsdoc": "^3.5.5"
"axios": "^0.18.0",
"cheerio": "^1.0.0-rc.2",
"dedent-js": "^1.0.1",
"htmlclean": "^3.0.8",
"jsdoc": "^3.5.5",
"pretty": "^2.0.0",
"request": "^2.85.0",
"rimraf": "^2.6.2"
},
"private": true
}

View file

@ -153,4 +153,4 @@ exports.defineTags = function (dictionary) {
doclet.hifiServerEntity = true;
}
});
};
};