Merge branch 'master' of github.com:highfidelity/hifi into 21616-addPerTileThreshold

This commit is contained in:
NissimHadar 2019-03-08 08:54:28 -08:00
commit 4caa5bd5b8
76 changed files with 4161 additions and 266 deletions

9
.gitignore vendored
View file

@ -99,12 +99,9 @@ tools/jsdoc/package-lock.json
# Python compile artifacts
**/__pycache__
# ignore unneeded unity project files for avatar exporter
tools/unity-avatar-exporter/Library
tools/unity-avatar-exporter/Logs
tools/unity-avatar-exporter/Packages
tools/unity-avatar-exporter/ProjectSettings
tools/unity-avatar-exporter/Temp
# ignore local unity project files for avatar exporter
tools/unity-avatar-exporter
server-console/package-lock.json
vcpkg/
/tools/nitpick/compiledResources

View file

@ -36,11 +36,6 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 26
//buildToolsVersion '27.0.3'
def appVersionCode = Integer.valueOf(VERSION_CODE ?: 1)
def appVersionName = RELEASE_NUMBER ?: "1.0"
defaultConfig {
applicationId "io.highfidelity.hifiinterface"
minSdkVersion 24

View file

@ -18,12 +18,11 @@ task renameHifiACTaskRelease(type: Copy) {
android {
compileSdkVersion 28
defaultConfig {
applicationId "io.highfidelity.questInterface"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionCode appVersionCode
versionName appVersionName
ndk { abiFilters 'arm64-v8a' }
externalNativeBuild {

View file

@ -273,11 +273,7 @@ ModalWindow {
onTriggered: {
root.result = null;
root.canceled();
// FIXME we are leaking memory to avoid a crash
// root.destroy();
root.disableFade = true
visible = false;
root.destroy();
}
}
@ -299,11 +295,7 @@ ModalWindow {
}
root.result = JSON.stringify(result);
root.selected(root.result);
// FIXME we are leaking memory to avoid a crash
// root.destroy();
root.disableFade = true
visible = false;
root.destroy();
}
}
}

View file

@ -815,7 +815,7 @@ ModalWindow {
Action {
id: cancelAction
text: "Cancel"
onTriggered: { canceled(); root.shown = false; }
onTriggered: { canceled(); root.destroy(); }
}
}

View file

@ -168,11 +168,7 @@ ModalWindow {
shortcut: "Esc"
onTriggered: {
root.canceled();
// FIXME we are leaking memory to avoid a crash
// root.destroy();
root.disableFade = true
visible = false;
root.destroy();
}
}
@ -183,11 +179,7 @@ ModalWindow {
onTriggered: {
root.result = items ? comboBox.currentText : textResult.text
root.selected(root.result);
// FIXME we are leaking memory to avoid a crash
// root.destroy();
root.disableFade = true
visible = false;
root.destroy();
}
}
}

View file

@ -41,6 +41,7 @@ Rectangle {
property string searchScopeString: "Featured"
property bool isLoggedIn: false
property bool supports3DHTML: true
property bool pendingGetMarketplaceItemCall: false
anchors.fill: (typeof parent === undefined) ? undefined : parent
@ -100,7 +101,9 @@ Rectangle {
getMarketplaceItems();
}
onGetMarketplaceItemsResult: {
marketBrowseModel.handlePage(result.status !== "success" && result.message, result);
if (!pendingGetMarketplaceItemCall) {
marketBrowseModel.handlePage(result.status !== "success" && result.message, result);
}
}
onGetMarketplaceItemResult: {
@ -127,6 +130,7 @@ Rectangle {
marketplaceItemScrollView.contentHeight = marketplaceItemContent.height;
itemsList.visible = false;
marketplaceItemView.visible = true;
pendingGetMarketplaceItemCall = false;
}
}
}
@ -1224,6 +1228,7 @@ Rectangle {
console.log("A message with method 'updateMarketplaceQMLItem' was sent without an itemId!");
return;
}
pendingGetMarketplaceItemCall = true;
marketplaceItem.edition = message.params.edition ? message.params.edition : -1;
MarketplaceScriptingInterface.getMarketplaceItem(message.params.itemId);
break;

View file

@ -52,13 +52,7 @@ Rectangle {
}
onDescriptionChanged: {
if(root.supports3DHTML) {
descriptionTextModel.clear();
descriptionTextModel.append({text: description});
} else {
descriptionText.text = description;
}
descriptionText.text = description;
}
onAttributionsChanged: {
@ -250,7 +244,6 @@ Rectangle {
function evalHeight() {
height = categoriesList.y - buyButton.y + categoriesList.height;
console.log("HEIGHT: " + height);
}
HifiControlsUit.Button {
@ -272,6 +265,9 @@ Rectangle {
text: isUpdate ? "UPDATE FOR FREE" : (isStocking ? "FREE STOCK" : (enabled ? (price || "FREE") : availability))
color: hifi.buttons.blue
buttonGlyphSize: 24
fontSize: 24
onClicked: root.buy();
}

View file

@ -226,6 +226,7 @@ Rectangle {
top: parent.top
left: parent.left
leftMargin: 15
topMargin: 10
}
width: paintedWidth
@ -241,7 +242,7 @@ Rectangle {
anchors {
top: creatorLabel.top;
left: creatorLabel.right;
leftMargin: 15;
leftMargin: 10;
}
width: paintedWidth;
@ -273,7 +274,7 @@ Rectangle {
anchors {
top: categoryLabel.top
left: categoryLabel.right
leftMargin: 15
leftMargin: 10
}
width: paintedWidth
@ -298,19 +299,21 @@ Rectangle {
topMargin:10
bottomMargin: 10
}
width: 180
property bool isNFS: availability === "not for sale" // Note: server will say "sold out" or "invalidated" before it says NFS
property bool isMine: creator === Account.username
property bool isUpgrade: root.edition >= 0
property int costToMe: ((isMine && isNFS) || isUpgrade) ? 0 : price
property bool isAvailable: costToMe >= 0
property bool isAvailable: availability === "available"
text: isUpgrade ? "UPGRADE FOR FREE" : (isAvailable ? (costToMe || "FREE") : availability)
enabled: isAvailable
buttonGlyph: isAvailable ? (costToMe ? hifi.glyphs.hfc : "") : ""
color: hifi.buttons.blue;
buttonGlyphSize: 24
fontSize: 24
onClicked: root.buy();
}
}

View file

@ -2346,6 +2346,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
} else {
QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
}
auto surfaceContext = webSurface->getSurfaceContext();
surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
} else {
// FIXME: the tablet should use the OffscreenQmlSurfaceCache
webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), [](OffscreenQmlSurface* webSurface) {
@ -3282,6 +3284,7 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona
surfaceContext->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
surfaceContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
if (setAdditionalContextProperties) {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
@ -3292,7 +3295,6 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona
surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
surfaceContext->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED

View file

@ -89,6 +89,8 @@ glm::vec3 RayPick::intersectRayWithEntityXYPlane(const QUuid& entityID, const gl
return intersectRayWithXYPlane(origin, direction, props.getPosition(), props.getRotation(), props.getRegistrationPoint());
}
glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized) {
glm::quat invRot = glm::inverse(rotation);
glm::vec3 localPos = invRot * (worldPos - position);
@ -102,6 +104,19 @@ glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3
return pos2D;
}
glm::vec2 RayPick::projectOntoXZPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized) {
glm::quat invRot = glm::inverse(rotation);
glm::vec3 localPos = invRot * (worldPos - position);
glm::vec3 normalizedPos = (localPos / dimensions) + registrationPoint;
glm::vec2 pos2D = glm::vec2(normalizedPos.x, (1.0f - normalizedPos.z));
if (unNormalized) {
pos2D *= glm::vec2(dimensions.x, dimensions.z);
}
return pos2D;
}
glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_POSITION;

View file

@ -86,6 +86,7 @@ public:
static glm::vec2 projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized = true);
static glm::vec2 projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNormalized);
static glm::vec2 projectOntoXZPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint, bool unNoemalized);
private:
static glm::vec3 intersectRayWithXYPlane(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& point, const glm::quat& rotation, const glm::vec3& registration);

View file

@ -155,15 +155,33 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) {
const auto entityRotation = entity->getWorldOrientation();
const auto entityPosition = entity->getWorldPosition();
const auto entityType = entity->getType();
glm::vec3 normal;
glm::vec3 normal = entityRotation * Vectors::UNIT_Z;
// TODO: Use the xz projection method for Sphere and Quad.
if (entityType == EntityTypes::Gizmo) {
normal = entityRotation * Vectors::UNIT_Y;
} else {
normal = entityRotation * Vectors::UNIT_Z;
}
float distance = glm::dot(pick.position - entityPosition, normal);
if (distance < nearestTarget.distance) {
const auto entityDimensions = entity->getScaledDimensions();
const auto entityRegistrationPoint = entity->getRegistrationPoint();
glm::vec3 intersection = pick.position - (normal * distance);
glm::vec2 pos2D = RayPick::projectOntoXYPlane(intersection, entityPosition, entityRotation,
entityDimensions, entityRegistrationPoint, false);
glm::vec2 pos2D;
auto entityType = entity->getType();
if (entityType == EntityTypes::Gizmo) {
pos2D = RayPick::projectOntoXZPlane(intersection, entityPosition, entityRotation,
entityDimensions, entityRegistrationPoint, false);
} else {
pos2D = RayPick::projectOntoXYPlane(intersection, entityPosition, entityRotation,
entityDimensions, entityRegistrationPoint, false);
}
if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) {
IntersectionType type = IntersectionType::ENTITY;
if (getFilter().doesPickLocalEntities()) {

View file

@ -65,7 +65,7 @@ static const glm::vec3 KEYBOARD_TABLET_OFFSET{0.30f, -0.38f, -0.04f};
static const glm::vec3 KEYBOARD_TABLET_DEGREES_OFFSET{-45.0f, 0.0f, 0.0f};
static const glm::vec3 KEYBOARD_TABLET_LANDSCAPE_OFFSET{-0.2f, -0.27f, -0.05f};
static const glm::vec3 KEYBOARD_TABLET_LANDSCAPE_DEGREES_OFFSET{-45.0f, 0.0f, -90.0f};
static const glm::vec3 KEYBOARD_AVATAR_OFFSET{-0.6f, 0.3f, -0.7f};
static const glm::vec3 KEYBOARD_AVATAR_OFFSET{-0.3f, 0.0f, -0.7f};
static const glm::vec3 KEYBOARD_AVATAR_DEGREES_OFFSET{0.0f, 180.0f, 0.0f};
static const QString SOUND_FILE = PathUtils::resourcesUrl() + "sounds/keyboardPress.mp3";
@ -373,6 +373,12 @@ void Keyboard::raiseKeyboardAnchor(bool raise) const {
void Keyboard::scaleKeyboard(float sensorToWorldScale) {
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
{
EntityItemProperties properties;
properties.setDimensions(_anchor.originalDimensions * sensorToWorldScale);
entityScriptingInterface->editEntity(_anchor.entityID, properties);
}
{
EntityItemProperties properties;
properties.setLocalPosition(_backPlate.localPosition * sensorToWorldScale);

View file

@ -11,7 +11,6 @@
#include "AnimPose.h"
#include <GLMHelpers.h>
#include <algorithm>
#include <glm/gtc/matrix_transform.hpp>
#include "AnimUtil.h"
const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
@ -19,16 +18,29 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
glm::vec3(0.0f));
AnimPose::AnimPose(const glm::mat4& mat) {
static const float EPSILON = 0.0001f;
_scale = extractScale(mat);
// quat_cast doesn't work so well with scaled matrices, so cancel it out.
glm::mat4 tmp = glm::scale(mat, 1.0f / _scale);
glm::mat3 m(mat);
_scale = glm::vec3(glm::length(m[0]), glm::length(m[1]), glm::length(m[2]));
float det = glm::determinant(m);
glm::mat3 tmp;
if (det < 0.0f) {
_scale *= -1.0f;
}
// quat_cast doesn't work so well with scaled matrices, so cancel out scale.
// also, as a side effect, multiply mirrored matrices by -1 to get the right rotation out.
tmp[0] = m[0] * (1.0f / _scale[0]);
tmp[1] = m[1] * (1.0f / _scale[1]);
tmp[2] = m[2] * (1.0f / _scale[2]);
_rot = glm::quat_cast(tmp);
// normalize quat if necessary
float lengthSquared = glm::length2(_rot);
if (glm::abs(lengthSquared - 1.0f) > EPSILON) {
float oneOverLength = 1.0f / sqrtf(lengthSquared);
_rot = glm::quat(_rot.w * oneOverLength, _rot.x * oneOverLength, _rot.y * oneOverLength, _rot.z * oneOverLength);
}
_trans = extractTranslation(mat);
}

View file

@ -156,7 +156,7 @@ const AnimPoseVec& AnimTwoBoneIK::evaluate(const AnimVariantMap& animVars, const
glm::quat relMidRot = glm::angleAxis(midAngle, _midHingeAxis);
// insert new relative pose into the chain and rebuild it.
ikChain.setRelativePoseAtJointIndex(_midJointIndex, AnimPose(relMidRot, underPoses[_midJointIndex].trans()));
ikChain.setRelativePoseAtJointIndex(_midJointIndex, AnimPose(underPoses[_midJointIndex].scale(), relMidRot, underPoses[_midJointIndex].trans()));
ikChain.buildDirtyAbsolutePoses();
// recompute tip pose after mid joint has been rotated
@ -180,7 +180,7 @@ const AnimPoseVec& AnimTwoBoneIK::evaluate(const AnimVariantMap& animVars, const
// transform result back into parent relative frame.
glm::quat relBaseRot = glm::inverse(baseParentPose.rot()) * absRot;
ikChain.setRelativePoseAtJointIndex(_baseJointIndex, AnimPose(relBaseRot, underPoses[_baseJointIndex].trans()));
ikChain.setRelativePoseAtJointIndex(_baseJointIndex, AnimPose(underPoses[_baseJointIndex].scale(), relBaseRot, underPoses[_baseJointIndex].trans()));
}
// recompute midJoint pose after base has been rotated.
@ -189,7 +189,7 @@ const AnimPoseVec& AnimTwoBoneIK::evaluate(const AnimVariantMap& animVars, const
// transform target rotation in to parent relative frame.
glm::quat relTipRot = glm::inverse(midJointPose.rot()) * targetPose.rot();
ikChain.setRelativePoseAtJointIndex(_tipJointIndex, AnimPose(relTipRot, underPoses[_tipJointIndex].trans()));
ikChain.setRelativePoseAtJointIndex(_tipJointIndex, AnimPose(underPoses[_tipJointIndex].scale(), relTipRot, underPoses[_tipJointIndex].trans()));
// blend with the underChain
ikChain.blend(underChain, alpha);

View file

@ -85,7 +85,7 @@ public:
void setUnscaledDimensions(const glm::vec3& value) override;
bool shouldBePhysical() const override { return !isDead(); }
bool supportsDetailedIntersection() const override;
bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElementPointer& element, float& distance,

View file

@ -257,7 +257,7 @@ template <typename T> struct GpuVec3ToGlm : GpuToGlmAdapter { static T get(con
case gpu::FLOAT: view.edit<glm::fvec3>(index) = value; return true;
case gpu::NUINT8: CHECK_SIZE(glm::uint32); view.edit<glm::uint32>(index) = glm::packUnorm4x8(glm::fvec4(value,0.0f)); return true;
case gpu::UINT8: view.edit<glm::u8vec3>(index) = value; return true;
case gpu::NINT2_10_10_10: view.edit<glm::uint32>(index) = glm::packSnorm3x10_1x2(glm::fvec4(value,0.0f)); return true;
case gpu::NINT2_10_10_10: view.edit<glm::uint32>(index) = glm_packSnorm3x10_1x2(glm::fvec4(value,0.0f)); return true;
default: break;
} error("GpuVec3ToGlm::set", view, index, hint); return false;
}
@ -295,7 +295,7 @@ template <typename T> struct GpuVec4ToGlm : GpuToGlmAdapter { static T get(const
case gpu::FLOAT: view.edit<glm::fvec4>(index) = value; return true;
case gpu::HALF: CHECK_SIZE(glm::uint64); view.edit<glm::uint64_t>(index) = glm::packHalf4x16(value); return true;
case gpu::UINT8: view.edit<glm::u8vec4>(index) = value; return true;
case gpu::NINT2_10_10_10: view.edit<glm::uint32>(index) = glm::packSnorm3x10_1x2(value); return true;
case gpu::NINT2_10_10_10: view.edit<glm::uint32>(index) = glm_packSnorm3x10_1x2(value); return true;
case gpu::NUINT16: CHECK_SIZE(glm::uint64); view.edit<glm::uint64>(index) = glm::packUnorm4x16(value); return true;
case gpu::NUINT8: CHECK_SIZE(glm::uint32); view.edit<glm::uint32>(index) = glm::packUnorm4x8(value); return true;
default: break;

View file

@ -46,30 +46,6 @@ namespace buffer_helpers {
gpu::BufferView clone(const gpu::BufferView& input);
gpu::BufferView resized(const gpu::BufferView& input, glm::uint32 numElements);
inline void packNormalAndTangent(glm::vec3 normal, glm::vec3 tangent, glm::uint32& packedNormal, glm::uint32& packedTangent) {
auto absNormal = glm::abs(normal);
auto absTangent = glm::abs(tangent);
normal /= glm::max(1e-6f, glm::max(glm::max(absNormal.x, absNormal.y), absNormal.z));
tangent /= glm::max(1e-6f, glm::max(glm::max(absTangent.x, absTangent.y), absTangent.z));
normal = glm::clamp(normal, -1.0f, 1.0f);
tangent = glm::clamp(tangent, -1.0f, 1.0f);
normal *= 511.0f;
tangent *= 511.0f;
glm::detail::i10i10i10i2 normalStruct;
glm::detail::i10i10i10i2 tangentStruct;
normalStruct.data.x = fastLrintf(normal.x);
normalStruct.data.y = fastLrintf(normal.y);
normalStruct.data.z = fastLrintf(normal.z);
normalStruct.data.w = 0;
tangentStruct.data.x = fastLrintf(tangent.x);
tangentStruct.data.y = fastLrintf(tangent.y);
tangentStruct.data.z = fastLrintf(tangent.z);
tangentStruct.data.w = 0;
packedNormal = normalStruct.pack;
packedTangent = tangentStruct.pack;
}
namespace mesh {
glm::uint32 forEachVertex(const graphics::MeshPointer& mesh, std::function<bool(glm::uint32 index, const QVariantMap& attributes)> func);
bool setVertexAttributes(const graphics::MeshPointer& mesh, glm::uint32 index, const QVariantMap& attributes);

View file

@ -125,8 +125,8 @@ void buildGraphicsMesh(const hfm::Mesh& hfmMesh, graphics::MeshPointer& graphics
#if HFM_PACK_NORMALS
const auto normal = normalizeDirForPacking(*normalIt);
const auto tangent = normalizeDirForPacking(*tangentIt);
const auto packedNormal = glm::packSnorm3x10_1x2(glm::vec4(normal, 0.0f));
const auto packedTangent = glm::packSnorm3x10_1x2(glm::vec4(tangent, 0.0f));
const auto packedNormal = glm_packSnorm3x10_1x2(glm::vec4(normal, 0.0f));
const auto packedTangent = glm_packSnorm3x10_1x2(glm::vec4(tangent, 0.0f));
#else
const auto packedNormal = *normalIt;
const auto packedTangent = *tangentIt;

View file

@ -8,10 +8,11 @@
#include "ParseFlowDataTask.h"
void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Input& mapping, Output& output) {
void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Input& mappingPair, Output& output) {
FlowData flowData;
static const QString FLOW_PHYSICS_FIELD = "flowPhysicsData";
static const QString FLOW_COLLISIONS_FIELD = "flowCollisionsData";
auto mapping = mappingPair.second;
for (auto mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) {
if (mappingIter.key() == FLOW_PHYSICS_FIELD || mappingIter.key() == FLOW_COLLISIONS_FIELD) {
QByteArray data = mappingIter.value().toByteArray();

View file

@ -12,9 +12,11 @@
#include <hfm/HFM.h>
#include "Engine.h"
#include "BakerTypes.h"
class ParseFlowDataTask {
public:
using Input = QVariantHash;
using Input = baker::GeometryMappingPair;
using Output = FlowData;
using JobModel = baker::Job::ModelIO<ParseFlowDataTask, Input, Output>;

View file

@ -1656,9 +1656,9 @@ void packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10(glm::uvec4& pac
packed = glm::uvec4(
glm::floatBitsToUint(len),
glm::packSnorm3x10_1x2(glm::vec4(normalizedPos, 0.0f)),
glm::packSnorm3x10_1x2(glm::vec4(unpacked.normalOffset, 0.0f)),
glm::packSnorm3x10_1x2(glm::vec4(unpacked.tangentOffset, 0.0f))
glm_packSnorm3x10_1x2(glm::vec4(normalizedPos, 0.0f)),
glm_packSnorm3x10_1x2(glm::vec4(unpacked.normalOffset, 0.0f)),
glm_packSnorm3x10_1x2(glm::vec4(unpacked.tangentOffset, 0.0f))
);
}

View file

@ -315,6 +315,42 @@ inline void glm_mat4u_mul(const glm::mat4& m1, const glm::mat4& m2, glm::mat4& r
#endif
}
//
// Fast replacement of glm::packSnorm3x10_1x2()
// The SSE2 version quantizes using round to nearest even.
// The glm version quantizes using round away from zero.
//
inline uint32_t glm_packSnorm3x10_1x2(vec4 const& v) {
union i10i10i10i2 {
struct {
int x : 10;
int y : 10;
int z : 10;
int w : 2;
} data;
uint32_t pack;
} Result;
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
__m128 vclamp = _mm_min_ps(_mm_max_ps(_mm_loadu_ps((float*)&v[0]), _mm_set1_ps(-1.0f)), _mm_set1_ps(1.0f));
__m128i vpack = _mm_cvtps_epi32(_mm_mul_ps(vclamp, _mm_setr_ps(511.f, 511.f, 511.f, 1.f)));
Result.data.x = _mm_cvtsi128_si32(vpack);
Result.data.y = _mm_cvtsi128_si32(_mm_shuffle_epi32(vpack, _MM_SHUFFLE(1,1,1,1)));
Result.data.z = _mm_cvtsi128_si32(_mm_shuffle_epi32(vpack, _MM_SHUFFLE(2,2,2,2)));
Result.data.w = _mm_cvtsi128_si32(_mm_shuffle_epi32(vpack, _MM_SHUFFLE(3,3,3,3)));
#else
ivec4 const Pack(round(clamp(v, -1.0f, 1.0f) * vec4(511.f, 511.f, 511.f, 1.f)));
Result.data.x = Pack.x;
Result.data.y = Pack.y;
Result.data.z = Pack.z;
Result.data.w = Pack.w;
#endif
return Result.pack;
}
// convert float to int, using round-to-nearest-even (undefined on overflow)
inline int fastLrintf(float x) {
#if GLM_ARCH & GLM_ARCH_SSE2_BIT

View file

@ -134,7 +134,7 @@ Script.include("/~/system/libraries/controllers.js");
var scaleModuleName = this.hand === RIGHT_HAND ? "RightScaleEntity" : "LeftScaleEntity";
var scaleModule = getEnabledModuleByName(scaleModuleName);
if (scaleModule.grabbedThingID || scaleModule.isReady(controllerData).active) {
if (scaleModule && (scaleModule.grabbedThingID || scaleModule.isReady(controllerData).active)) {
// we're rescaling -- don't start a grab.
return makeRunningValues(false, [], []);
}

View file

@ -247,8 +247,8 @@ Script.include("/~/system/libraries/controllers.js");
this.run = function(controllerData, deltaTime) {
this.addObjectToIgnoreList(controllerData);
var type = this.getInteractableType(controllerData, isTriggerPressed, false);
var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE;
var type = this.getInteractableType(controllerData, isTriggerPressed, false);
var laserOn = isTriggerPressed || this.parameters.handLaser.alwaysOn;
this.addObjectToIgnoreList(controllerData);

View file

@ -30,7 +30,6 @@ var CONTOLLER_SCRIPTS = [
"controllerModules/teleport.js",
"controllerModules/hudOverlayPointer.js",
"controllerModules/mouseHMD.js",
"controllerModules/scaleEntity.js",
"controllerModules/nearGrabHyperLinkEntity.js",
"controllerModules/nearTabletHighlight.js",
"controllerModules/nearGrabEntity.js",

View file

@ -1492,6 +1492,8 @@ const ENTITY_SCRIPT_STATUS = {
unloaded: "Unloaded"
};
const ENABLE_DISABLE_SELECTOR = "input, textarea, span, .dropdown dl, .color-picker";
const PROPERTY_NAME_DIVISION = {
GROUP: 0,
PROPERTY: 1,
@ -1591,8 +1593,7 @@ function disableChildren(el, selector) {
}
function enableProperties() {
enableChildren(document.getElementById("properties-list"),
"input, textarea, checkbox, .dropdown dl, .color-picker , .draggable-number.text");
enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR);
enableChildren(document, ".colpick");
let elLocked = getPropertyInputElement("locked");
@ -1603,8 +1604,7 @@ function enableProperties() {
}
function disableProperties() {
disableChildren(document.getElementById("properties-list"),
"input, textarea, checkbox, .dropdown dl, .color-picker, .draggable-number.text");
disableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR);
disableChildren(document, ".colpick");
for (let pickKey in colorPickers) {
colorPickers[pickKey].colpickHide();
@ -3356,8 +3356,8 @@ function loaded() {
let shouldHide = selectedEntityProperties.certificateID !== "";
if (shouldHide) {
propertyValue = "** Certified **";
property.elInput.disabled = true;
}
property.elInput.disabled = shouldHide;
}
let isPropertyNotNumber = false;

View file

@ -176,7 +176,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) {
this.homeButtonID = Overlays.addOverlay("circle3d", {
name: "homeButton",
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},
localRotation: Quat.fromVec3Degrees({ x: 180, y: 180, z: 0}),
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim },
solid: true,
alpha: 0.0,
@ -189,7 +189,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) {
this.homeButtonHighlightID = Overlays.addOverlay("circle3d", {
name: "homeButtonHighlight",
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},
localRotation: Quat.fromVec3Degrees({ x: 180, y: 180, z: 0}),
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim },
color: {red: 255, green: 255, blue: 255},
solid: true,

View file

@ -1,7 +1,7 @@
# Declare dependencies
macro (setup_testcase_dependencies)
# link in the shared libraries
link_hifi_libraries(shared animation gpu fbx hfm graphics networking test-utils)
link_hifi_libraries(shared animation gpu fbx hfm graphics networking test-utils image)
package_libraries_for_deployment()
endmacro ()

View file

@ -443,6 +443,28 @@ void AnimTests::testAnimPose() {
}
}
}
// test matrix that has a negative determiant.
glm::vec4 col0(-9.91782e-05f, -5.40349e-05f, 0.000724383f, 0.0f);
glm::vec4 col1(-0.000155237f, 0.00071579f, 3.21398e-05f, 0.0f);
glm::vec4 col2(0.000709614f, 0.000149036f, 0.000108273f, 0.0f);
glm::vec4 col3(0.117922f, 0.250457f, 0.102155f, 1.0f);
glm::mat4 m(col0, col1, col2, col3);
AnimPose p(m);
glm::vec3 resultTrans = glm::vec3(col3);
glm::quat resultRot = glm::quat(0.0530394f, 0.751549f, 0.0949531f, -0.650649f);
glm::vec3 resultScale = glm::vec3(-0.000733135f, -0.000733135f, -0.000733135f);
const float TEST_EPSILON2 = 0.00001f;
QCOMPARE_WITH_ABS_ERROR(p.trans(), resultTrans, TEST_EPSILON2);
if (glm::dot(p.rot(), resultRot) < 0.0f) {
resultRot = -resultRot;
}
QCOMPARE_WITH_ABS_ERROR(p.rot(), resultRot, TEST_EPSILON2);
QCOMPARE_WITH_ABS_ERROR(p.scale(), resultScale, TEST_EPSILON2);
}
void AnimTests::testExpressionTokenizer() {

View file

@ -1,4 +1,17 @@
{
"opts": {
"template": "hifi-jsdoc-template"
},
"docdash": {
"meta": {
"title": "",
"description": "",
"keyword": ""
},
"search": [true],
"collapse": [true],
"typedefs": [false]
},
"templates": {
"default": {
"outputSourceFiles": false

View file

@ -0,0 +1,61 @@
# License
Docdash is free software, licensed under the Apache License, Version 2.0 (the
"License"). Commercial and non-commercial use are permitted in compliance with
the License.
Copyright (c) 2016 Clement Moron <clenemt@gmail.com> and the
[contributors to docdash](https://github.com/clenemt/docdash/graphs/contributors).
All rights reserved.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
In addition, a copy of the License is included with this distribution.
As stated in Section 7, "Disclaimer of Warranty," of the License:
> Licensor provides the Work (and each Contributor provides its Contributions)
> on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
> express or implied, including, without limitation, any warranties or
> conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
> PARTICULAR PURPOSE. You are solely responsible for determining the
> appropriateness of using or redistributing the Work and assume any risks
> associated with Your exercise of permissions under this License.
The source code for docdash is available at:
https://github.com/clenemt/docdash
# Third-Party Software
Docdash includes or depends upon the following third-party software, either in
whole or in part. Each third-party software package is provided under its own
license.
## JSDoc 3
JSDoc 3 is free software, licensed under the Apache License, Version 2.0 (the
"License"). Commercial and non-commercial use are permitted in compliance with
the License.
Copyright (c) 2011-2016 Michael Mathews <micmath@gmail.com> and the
[contributors to JSDoc](https://github.com/jsdoc3/jsdoc/graphs/contributors).
All rights reserved.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
In addition, a copy of the License is included with this distribution.
As stated in Section 7, "Disclaimer of Warranty," of the License:
> Licensor provides the Work (and each Contributor provides its Contributions)
> on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
> express or implied, including, without limitation, any warranties or
> conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
> PARTICULAR PURPOSE. You are solely responsible for determining the
> appropriateness of using or redistributing the Work and assume any risks
> associated with Your exercise of permissions under this License.
The source code for JSDoc 3 is available at:
https://github.com/jsdoc3/jsdoc

View file

@ -0,0 +1,42 @@
# hifi-jsdoc-template
The hifi-jsdoc-template is based on the [DocDash](https://github.com/clenemt/docdash) template.
## Usage
Clone repository to your designated `jsdoc/node_modules` template directory.
In your `config.json` file, add a template option.
```json
"opts": {
"template": "node_modules/hifi-jsdoc-template"
}
```
## Sample `config.json`
```json
{
"opts": {
"template": "node_modules/hifi-jsdoc-template"
},
"docdash": {
"meta": {
"title": "",
"description": "",
"keyword": ""
},
"search": [true],
"collapse": [true],
"typedefs": [false]
},
"templates": {
"default": {
"outputSourceFiles": false
}
},
"plugins": [
"plugins/hifi",
"plugins/hifiJSONExport"
]
}
```

View file

@ -0,0 +1,59 @@
{
"_from": "docdash",
"_id": "docdash@1.0.0",
"_inBundle": false,
"_integrity": "sha512-HhK72PT4z55og8FDqskO/tTYXxU+LovRz+9pCDHLnUoPchkxjdIJidS+96LqW3CLrRdBmnkDRrcVrDFGLIluTw==",
"_location": "/docdash",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "docdash",
"name": "docdash",
"escapedName": "docdash",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/docdash/-/docdash-1.0.0.tgz",
"_shasum": "5b7df10fed3d341fc4416a8978c65ad561869d18",
"_spec": "docdash",
"_where": "D:\\hifi\\tools\\jsdoc",
"author": {
"name": "Clement Moron",
"email": "clement.moron@gmail.com"
},
"bugs": {
"url": "https://github.com/clenemt/docdash/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "A clean, responsive documentation template theme for JSDoc 3 inspired by lodash and minami",
"devDependencies": {
"browser-sync": "latest",
"jsdoc": "latest",
"watch-run": "latest"
},
"homepage": "https://github.com/clenemt/docdash#readme",
"keywords": [
"jsdoc",
"template"
],
"license": "Apache-2.0",
"main": "publish.js",
"name": "docdash",
"repository": {
"type": "git",
"url": "git+https://github.com/clenemt/docdash.git"
},
"scripts": {
"sync": "browser-sync start -s ../fixtures-doc -f ../fixtures-doc --reload-delay 1000 --no-ui --no-notify",
"test": "jsdoc -c fixtures/fixtures.conf.json",
"watch": "watch-run -d 1000 -p tmpl/**,static/** \"npm run test\""
},
"version": "1.0.0"
}

View file

@ -0,0 +1,772 @@
/*global env: true */
'use strict';
var doop = require('jsdoc/util/doop');
var fs = require('jsdoc/fs');
var helper = require('jsdoc/util/templateHelper');
var logger = require('jsdoc/util/logger');
var path = require('jsdoc/path');
var taffy = require('taffydb').taffy;
var template = require('jsdoc/template');
var util = require('util');
var htmlsafe = helper.htmlsafe;
var linkto = helper.linkto;
var resolveAuthorLinks = helper.resolveAuthorLinks;
var scopeToPunc = helper.scopeToPunc;
var hasOwnProp = Object.prototype.hasOwnProperty;
var data;
var view;
var outdir = path.normalize(env.opts.destination);
function copyFile(source, target, cb) {
var cbCalled = false;
var rd = fs.createReadStream(source);
rd.on("error", function(err) {
done(err);
});
var wr = fs.createWriteStream(target);
wr.on("error", function(err) {
done(err);
});
wr.on("close", function(ex) {
done();
});
rd.pipe(wr);
function done(err) {
if (!cbCalled) {
cb(err);
cbCalled = true;
}
}
}
function find(spec) {
return helper.find(data, spec);
}
function tutoriallink(tutorial) {
return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' });
}
function getAncestorLinks(doclet) {
return helper.getAncestorLinks(data, doclet);
}
function hashToLink(doclet, hash) {
if ( !/^(#.+)/.test(hash) ) { return hash; }
var url = helper.createLink(doclet);
url = url.replace(/(#.+|$)/, hash);
return '<a href="' + url + '">' + hash + '</a>';
}
function needsSignature(doclet) {
var needsSig = false;
// function and class definitions always get a signature
if (doclet.kind === 'function' || doclet.kind === 'class' && !doclet.hideconstructor) {
needsSig = true;
}
// typedefs that contain functions get a signature, too
else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names &&
doclet.type.names.length) {
for (var i = 0, l = doclet.type.names.length; i < l; i++) {
if (doclet.type.names[i].toLowerCase() === 'function') {
needsSig = true;
break;
}
}
}
return needsSig;
}
function getSignatureAttributes(item) {
var attributes = [];
if (item.optional) {
attributes.push('opt');
}
if (item.nullable === true) {
attributes.push('nullable');
}
else if (item.nullable === false) {
attributes.push('non-null');
}
return attributes;
}
function updateItemName(item) {
var attributes = getSignatureAttributes(item);
var itemName = item.name || '';
if (item.variable) {
itemName = '&hellip;' + itemName;
}
if (attributes && attributes.length) {
itemName = util.format( '%s<span class="signature-attributes">%s</span>', itemName,
attributes.join(', ') );
}
return itemName;
}
function addParamAttributes(params) {
return params.filter(function(param) {
return param.name && param.name.indexOf('.') === -1;
}).map(updateItemName);
}
function buildItemTypeStrings(item) {
var types = [];
if (item && item.type && item.type.names) {
item.type.names.forEach(function(name) {
types.push( linkto(name, htmlsafe(name)) );
});
}
return types;
}
function buildAttribsString(attribs) {
var attribsString = '';
if (attribs && attribs.length) {
attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) );
}
return attribsString;
}
function addNonParamAttributes(items) {
var types = [];
items.forEach(function(item) {
types = types.concat( buildItemTypeStrings(item) );
});
return types;
}
function addSignatureParams(f) {
var params = f.params ? addParamAttributes(f.params) : [];
f.signature = util.format( '%s( %s )', (f.signature || ''), params.join(', ') );
}
function addSignatureReturns(f) {
var attribs = [];
var attribsString = '';
var returnTypes = [];
var returnTypesString = '';
// jam all the return-type attributes into an array. this could create odd results (for example,
// if there are both nullable and non-nullable return types), but let's assume that most people
// who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa.
if (f.returns) {
f.returns.forEach(function(item) {
helper.getAttribs(item).forEach(function(attrib) {
if (attribs.indexOf(attrib) === -1) {
attribs.push(attrib);
}
});
});
attribsString = buildAttribsString(attribs);
}
if (f.returns) {
returnTypes = addNonParamAttributes(f.returns);
}
if (returnTypes.length) {
returnTypesString = util.format( ' &rarr; %s{%s}', attribsString, returnTypes.join('|') );
}
f.signature = '<span class="signature">' + (f.signature || '') + '</span>' +
'<span class="type-returns">' + returnTypesString + '</span>';
}
function addSignatureTypes(f) {
var types = f.type ? buildItemTypeStrings(f) : [];
f.signature = (f.signature || '') + '<span class="type-signature">' +
(types.length ? ' :' + types.join('|') : '') + '</span>';
}
function addAttribs(f) {
var attribs = helper.getAttribs(f);
var attribsString = buildAttribsString(attribs);
f.attribs = util.format('<span class="type-signature">%s</span>', attribsString);
}
function shortenPaths(files, commonPrefix) {
Object.keys(files).forEach(function(file) {
files[file].shortened = files[file].resolved.replace(commonPrefix, '')
// always use forward slashes
.replace(/\\/g, '/');
});
return files;
}
function getPathFromDoclet(doclet) {
if (!doclet.meta) {
return null;
}
return doclet.meta.path && doclet.meta.path !== 'null' ?
path.join(doclet.meta.path, doclet.meta.filename) :
doclet.meta.filename;
}
function generate(type, title, docs, filename, resolveLinks) {
resolveLinks = resolveLinks === false ? false : true;
var docData = {
type: type,
title: title,
docs: docs
};
var outpath = path.join(outdir, filename),
html = view.render('container.tmpl', docData);
if (resolveLinks) {
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
}
fs.writeFileSync(outpath, html, 'utf8');
}
function generateSourceFiles(sourceFiles, encoding) {
encoding = encoding || 'utf8';
Object.keys(sourceFiles).forEach(function(file) {
var source;
// links are keyed to the shortened path in each doclet's `meta.shortpath` property
var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened);
helper.registerLink(sourceFiles[file].shortened, sourceOutfile);
try {
source = {
kind: 'source',
code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) )
};
}
catch(e) {
logger.error('Error while generating source file %s: %s', file, e.message);
}
generate('Source', sourceFiles[file].shortened, [source], sourceOutfile, false);
});
}
/**
* Look for classes or functions with the same name as modules (which indicates that the module
* exports only that class or function), then attach the classes or functions to the `module`
* property of the appropriate module doclets. The name of each class or function is also updated
* for display purposes. This function mutates the original arrays.
*
* @private
* @param {Array.<module:jsdoc/doclet.Doclet>} doclets - The array of classes and functions to
* check.
* @param {Array.<module:jsdoc/doclet.Doclet>} modules - The array of module doclets to search.
*/
function attachModuleSymbols(doclets, modules) {
var symbols = {};
// build a lookup table
doclets.forEach(function(symbol) {
symbols[symbol.longname] = symbols[symbol.longname] || [];
symbols[symbol.longname].push(symbol);
});
return modules.map(function(module) {
if (symbols[module.longname]) {
module.modules = symbols[module.longname]
// Only show symbols that have a description. Make an exception for classes, because
// we want to show the constructor-signature heading no matter what.
.filter(function(symbol) {
return symbol.description || symbol.kind === 'class';
})
.map(function(symbol) {
symbol = doop(symbol);
if (symbol.kind === 'class' || symbol.kind === 'function' && !symbol.hideconstructor) {
symbol.name = symbol.name.replace('module:', '(require("') + '"))';
}
return symbol;
});
}
});
}
function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) {
var nav = '';
if (items && items.length) {
var itemsNav = '';
items.forEach(function(item) {
var displayName;
var methods = find({kind:'function', memberof: item.longname});
var signals = find({kind:'signal', memberof: item.longname});
var members = find({kind:'member', memberof: item.longname});
var docdash = env && env.conf && env.conf.docdash || {};
var conf = env && env.conf || {};
if ( !hasOwnProp.call(item, 'longname') ) {
itemsNav += '<li>' + linktoFn('', item.name);
itemsNav += '</li>';
} else if ( !hasOwnProp.call(itemsSeen, item.longname) ) {
if (conf.templates.default.useLongnameInNav) {
displayName = item.longname;
} else {
displayName = item.name;
}
itemsNav += '<li>' + linktoFn(item.longname, displayName.replace(/\b(module|event):/g, ''));
if (docdash.static && members.find(function (m) { return m.scope === 'static'; } )) {
itemsNav += "<ul class='members'>";
members.forEach(function (member) {
if (!member.scope === 'static') return;
itemsNav += "<li data-type='member'";
if(docdash.collapse)
itemsNav += " style='display: none;'";
itemsNav += ">";
itemsNav += linkto(member.longname, member.name);
itemsNav += "</li>";
});
itemsNav += "</ul>";
}
if (methods.length) {
itemsNav += "<ul class='methods'>";
methods.forEach(function (method) {
itemsNav += "<li data-type='method'";
if(docdash.collapse)
itemsNav += " style='display: none;'";
itemsNav += ">";
itemsNav += linkto(method.longname, method.name);
itemsNav += "</li>";
});
itemsNav += "</ul>";
}
if (signals.length) {
itemsNav += "<ul class='methods'>";
signals.forEach(function (signal) {
itemsNav += "<li data-type='method'";
if(docdash.collapse)
itemsNav += " style='display: none;'";
itemsNav += ">";
itemsNav += linkto(signal.longname, signal.name);
itemsNav += "</li>";
});
itemsNav += "</ul>";
}
itemsNav += '</li>';
itemsSeen[item.longname] = true;
}
});
if (itemsNav !== '') {
nav += '<h3>' + itemHeading + '</h3><ul class="nav">' + itemsNav + '</ul>';
}
}
return nav;
}
function linktoTutorial(longName, name) {
return tutoriallink(name);
}
function linktoExternal(longName, name) {
return linkto(longName, name.replace(/(^"|"$)/g, ''));
}
/**
* Create the navigation sidebar.
* @param {object} members The members that will be used to create the sidebar.
* @param {array<object>} members.classes
* @param {array<object>} members.externals
* @param {array<object>} members.globals
* @param {array<object>} members.mixins
* @param {array<object>} members.modules
* @param {array<object>} members.namespaces
* @param {array<object>} members.tutorials
* @param {array<object>} members.events
* @param {array<object>} members.interfaces
* @return {s
ring} The HTML for the navigation sidebar.
*/
function buildNav(members) {
var nav = '<h3><a href="index.html">Home</a></h3>';
var seen = {};
var seenTutorials = {};
var docdash = env && env.conf && env.conf.docdash || {};
if(docdash.menu){
for(var menu in docdash.menu){
nav += '<h2><a ';
//add attributes
for(var attr in docdash.menu[menu]){
nav += attr+'="' + docdash.menu[menu][attr] + '" ';
}
nav += '>' + menu + '</a></h2>';
}
}
var defaultOrder = [
'Namespaces', 'Classes', 'Modules', 'Externals', 'Events', 'Mixins', 'Tutorials', 'Interfaces'
];
var order = docdash.sectionOrder || defaultOrder;
var sections = {
Namespaces: buildMemberNav(members.namespaces, 'Namespaces', seen, linkto),
Classes: buildMemberNav(members.classes, 'Classes', seen, linkto),
Modules: buildMemberNav(members.modules, 'Modules', {}, linkto),
Externals: buildMemberNav(members.externals, 'Externals', seen, linktoExternal),
Events: buildMemberNav(members.events, 'Events', seen, linkto),
Mixins: buildMemberNav(members.mixins, 'Mixins', seen, linkto),
Tutorials: buildMemberNav(members.tutorials, 'Tutorials', seenTutorials, linktoTutorial),
Interfaces: buildMemberNav(members.interfaces, 'Interfaces', seen, linkto),
};
order.forEach(member => nav += sections[member]);
if (members.globals.length) {
var globalNav = '';
members.globals.forEach(function(g) {
if ( (docdash.typedefs || g.kind !== 'typedef') && !hasOwnProp.call(seen, g.longname) ) {
globalNav += '<li>' + linkto(g.longname, g.name) + '</li>';
}
seen[g.longname] = true;
});
if (!globalNav) {
// turn the heading into a link so you can actually get to the global page
nav += '<h3>' + linkto('global', 'Global') + '</h3>';
}
else {
nav += '<h3>Globals</h3><ul>' + globalNav + '</ul>';
}
}
return nav;
}
/**
@param {TAFFY} taffyData See <http://taffydb.com/>.
@param {object} opts
@param {Tutorial} tutorials
*/
exports.publish = function(taffyData, opts, tutorials) {
var docdash = env && env.conf && env.conf.docdash || {};
data = taffyData;
var conf = env.conf.templates || {};
conf.default = conf.default || {};
var templatePath = path.normalize(opts.template);
view = new template.Template( path.join(templatePath, 'tmpl') );
// claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
// doesn't try to hand them out later
var indexUrl = helper.getUniqueFilename('index');
// don't call registerLink() on this one! 'index' is also a valid longname
var globalUrl = helper.getUniqueFilename('global');
helper.registerLink('global', globalUrl);
// set up templating
view.layout = conf.default.layoutFile ?
path.getResourcePath(path.dirname(conf.default.layoutFile),
path.basename(conf.default.layoutFile) ) :
'layout.tmpl';
// set up tutorials for helper
helper.setTutorials(tutorials);
data = helper.prune(data);
docdash.sort !== false && data.sort('longname, version, since');
helper.addEventListeners(data);
var sourceFiles = {};
var sourceFilePaths = [];
data().each(function(doclet) {
if(docdash.removeQuotes){
if(docdash.removeQuotes === "all"){
if(doclet.name){
doclet.name = doclet.name.replace(/"/g, '');
doclet.name = doclet.name.replace(/'/g, '');
}
if(doclet.longname){
doclet.longname = doclet.longname.replace(/"/g, '');
doclet.longname = doclet.longname.replace(/'/g, '');
}
}
else if(docdash.removeQuotes === "trim"){
if(doclet.name){
doclet.name = doclet.name.replace(/^"(.*)"$/, '$1');
doclet.name = doclet.name.replace(/^'(.*)'$/, '$1');
}
if(doclet.longname){
doclet.longname = doclet.longname.replace(/^"(.*)"$/, '$1');
doclet.longname = doclet.longname.replace(/^'(.*)'$/, '$1');
}
}
}
doclet.attribs = '';
if (doclet.examples) {
doclet.examples = doclet.examples.map(function(example) {
var caption, code;
if (example && example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
caption = RegExp.$1;
code = RegExp.$3;
}
return {
caption: caption || '',
code: code || example || ''
};
});
}
if (doclet.see) {
doclet.see.forEach(function(seeItem, i) {
doclet.see[i] = hashToLink(doclet, seeItem);
});
}
// build a list of source files
var sourcePath;
if (doclet.meta) {
sourcePath = getPathFromDoclet(doclet);
sourceFiles[sourcePath] = {
resolved: sourcePath,
shortened: null
};
if (sourceFilePaths.indexOf(sourcePath) === -1) {
sourceFilePaths.push(sourcePath);
}
}
});
// update outdir if necessary, then create outdir
var packageInfo = ( find({kind: 'package'}) || [] ) [0];
if (packageInfo && packageInfo.name) {
outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') );
}
fs.mkPath(outdir);
// copy the template's static files to outdir
var fromDir = path.join(templatePath, 'static');
var staticFiles = fs.ls(fromDir, 3);
staticFiles.forEach(function(fileName) {
var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
fs.mkPath(toDir);
copyFile(fileName, path.join(toDir, path.basename(fileName)), function(err){if(err) console.err(err);});
});
// copy user-specified static files to outdir
var staticFilePaths;
var staticFileFilter;
var staticFileScanner;
if (conf.default.staticFiles) {
// The canonical property name is `include`. We accept `paths` for backwards compatibility
// with a bug in JSDoc 3.2.x.
staticFilePaths = conf.default.staticFiles.include ||
conf.default.staticFiles.paths ||
[];
staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles);
staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();
staticFilePaths.forEach(function(filePath) {
var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);
extraStaticFiles.forEach(function(fileName) {
var sourcePath = fs.toDir(filePath);
var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
fs.mkPath(toDir);
copyFile(fileName, path.join(toDir, path.basename(fileName)), function(err){if(err) console.err(err);});
});
});
}
if (sourceFilePaths.length) {
sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
}
data().each(function(doclet) {
var url = helper.createLink(doclet);
helper.registerLink(doclet.longname, url);
// add a shortened version of the full path
var docletPath;
if (doclet.meta) {
docletPath = getPathFromDoclet(doclet);
docletPath = sourceFiles[docletPath].shortened;
if (docletPath) {
doclet.meta.shortpath = docletPath;
}
}
});
data().each(function(doclet) {
var url = helper.longnameToUrl[doclet.longname];
if (url.indexOf('#') > -1) {
doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
}
else {
doclet.id = doclet.name;
}
if ( needsSignature(doclet) ) {
addSignatureParams(doclet);
addSignatureReturns(doclet);
addAttribs(doclet);
}
});
// do this after the urls have all been generated
data().each(function(doclet) {
doclet.ancestors = getAncestorLinks(doclet);
if (doclet.kind === 'member') {
addSignatureTypes(doclet);
addAttribs(doclet);
}
if (doclet.kind === 'constant') {
addSignatureTypes(doclet);
addAttribs(doclet);
doclet.kind = 'member';
}
});
var members = helper.getMembers(data);
members.tutorials = tutorials.children;
// output pretty-printed source files by default
var outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false
? true
: false;
// add template helpers
view.find = find;
view.linkto = linkto;
view.resolveAuthorLinks = resolveAuthorLinks;
view.tutoriallink = tutoriallink;
view.htmlsafe = htmlsafe;
view.outputSourceFiles = outputSourceFiles;
// once for all
view.nav = buildNav(members);
attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules );
// generate the pretty-printed source files first so other pages can link to them
if (outputSourceFiles) {
generateSourceFiles(sourceFiles, opts.encoding);
}
if (members.globals.length) {
generate('', 'Global', [{kind: 'globalobj'}], globalUrl);
}
// index page displays information from package.json and lists files
var files = find({kind: 'file'});
var packages = find({kind: 'package'});
generate('', 'High Fidelity API Reference',
packages.concat(
[{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
).concat(files),
indexUrl);
// set up the lists that we'll use to generate pages
var classes = taffy(members.classes);
var modules = taffy(members.modules);
var namespaces = taffy(members.namespaces);
var mixins = taffy(members.mixins);
var externals = taffy(members.externals);
var interfaces = taffy(members.interfaces);
Object.keys(helper.longnameToUrl).forEach(function(longname) {
var myModules = helper.find(modules, {longname: longname});
if (myModules.length) {
generate('Module', myModules[0].name, myModules, helper.longnameToUrl[longname]);
}
var myClasses = helper.find(classes, {longname: longname});
if (myClasses.length) {
generate('Class', myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
}
var myNamespaces = helper.find(namespaces, {longname: longname});
if (myNamespaces.length) {
generate('Namespace', myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
}
var myMixins = helper.find(mixins, {longname: longname});
if (myMixins.length) {
generate('Mixin', myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
}
var myExternals = helper.find(externals, {longname: longname});
if (myExternals.length) {
generate('External', myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
}
var myInterfaces = helper.find(interfaces, {longname: longname});
if (myInterfaces.length) {
generate('Interface', myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]);
}
});
// TODO: move the tutorial functions to templateHelper.js
function generateTutorial(title, tutorial, filename) {
var tutorialData = {
title: title,
header: tutorial.title,
content: tutorial.parse(),
children: tutorial.children
};
var tutorialPath = path.join(outdir, filename);
var html = view.render('tutorial.tmpl', tutorialData);
// yes, you can use {@link} in tutorials too!
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
fs.writeFileSync(tutorialPath, html, 'utf8');
}
// tutorials can have only one parent so there is no risk for loops
function saveChildren(node) {
node.children.forEach(function(child) {
generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
saveChildren(child);
});
}
saveChildren(tutorials);
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -0,0 +1,11 @@
function hideAllButCurrent(){
//by default all submenut items are hidden
$("nav > ul > li > ul li").hide();
//only current page (if it exists) should be opened
var file = window.location.pathname.split("/").pop();
$("nav > ul > li > a[href^='"+file+"']").parent().find("> ul li").show();
}
$( document ).ready(function() {
hideAllButCurrent();
});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,25 @@
/*global document */
(function() {
var source = document.getElementsByClassName('prettyprint source linenums');
var i = 0;
var lineNumber = 0;
var lineId;
var lines;
var totalLines;
var anchorHash;
if (source && source[0]) {
anchorHash = document.location.hash.substring(1);
lines = source[0].getElementsByTagName('li');
totalLines = lines.length;
for (; i < totalLines; i++) {
lineNumber++;
lineId = 'line' + lineNumber;
lines[i].id = lineId;
if (lineId === anchorHash) {
lines[i].className += ' selected';
}
}
}
})();

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,2 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);

View file

@ -0,0 +1,28 @@
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

View file

@ -0,0 +1,42 @@
$( document ).ready(function() {
jQuery.expr[':'].Contains = function(a,i,m){
return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
};
//on search
$("#nav-search").on("keyup", function(event) {
var search = $(this).val();
if (!search) {
//no search, show all results
$("nav > ul > li").show();
if(typeof hideAllButCurrent === "function"){
//let's do what ever collapse wants to do
hideAllButCurrent();
}
else{
//menu by default should be opened
$("nav > ul > li > ul li").show();
}
}
else{
//we are searching
//show all parents
$("nav > ul > li").show();
//hide all results
$("nav > ul > li > ul li").hide();
//show results matching filter
$("nav > ul > li > ul").find("a:Contains("+search+")").parent().show();
//hide parents without children
$("nav > ul > li").each(function(){
if($(this).find("a:Contains("+search+")").length == 0 && $(this).children("ul").length === 0){
//has no child at all and does not contain text
$(this).hide();
}
else if($(this).find("a:Contains("+search+")").length == 0 && $(this).find("ul").children(':visible').length == 0){
//has no visible child and does not contain text
$(this).hide();
}
});
}
});
});

View file

@ -0,0 +1,731 @@
/*******************************************************************
****************************** Font styles *************************
********************************************************************/
@font-face{
font-family: 'Cairo';
src: url('../fonts/Cairo-Bold.ttf') format('truetype');
}
@font-face{
font-family: 'Proxima Nova';
src: url('../fonts/proximanova-regular.otf') format('opentype');
}
/*******************************************************************
**************************** General styles ************************
********************************************************************/
* {
box-sizing: border-box
}
html
{
overflow: auto;
background-color: #fff;
}
body
{
font-family: 'Proxima Nova', sans-serif;
font-size: 1rem;
line-height: 1.5;
letter-spacing: 0.5px;
margin: 1.5rem;
color: #555;
}
section
{
display: block;
background-color: #fff;
padding: 12px 24px;
margin-right: 30px;
}
/*******************************************************************
**************************** Heading styles ************************
********************************************************************/
h1, h2, h3, h4 {
font-family: "Cairo", Helvetica, sans-serif;
}
h1
{
font-size: 3.25rem;
text-align: center;
letter-spacing: 1.5px;
margin: 50px 25px 25px;
}
h2
{
font-size: 2.55rem;
margin-bottom: 12px;
}
h3
{
font-size: 1.5rem;
}
h4
{
font-size: 18px;
letter-spacing: -0.33px;
margin-bottom: 12px;
color: #4d4e53;
}
h6
{
font-size: 100%;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
font-style: italic;
}
.paramHeading, .typeDef h3.propsHeading, h3.subHeading
{
font-size: .9rem;
font-family: "Proxima Nova";
font-weight: bold;
border-bottom: solid 1px #ddd;
}
h4.name
{
margin-bottom: 0px;
padding-bottom: 0px;
}
h5, .container-overview .subsection-title
{
font-size: 13px;
font-weight: bold;
margin-bottom: 5px;
}
/*******************************************************************
**************************** Table styles **************************
********************************************************************/
table
{
width: 100%;
background-color: #fff;
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #ccc;
text-align: left;
overflow: auto;
font-size: 0.9rem;
line-height: 1.5;
margin-bottom: 1.5rem;
}
table > thead {
background-color: #ddd;
border-bottom: 1px solid #ccc;
font-weight: 400;
}
table th, table td {
padding: 0.5rem;
border-left: 1px solid #ccc;
}
table tr {
border-bottom: 1px solid #ccc;
}
table tr:nth-child(even) {
background-color: #f8f8f8;
}
/*******************************************************************
****************************** Link styles *************************
********************************************************************/
a, a:visited, a:active {
color: #1694CA;
text-decoration: none;
}
article a:hover {
color: #0e6185;
text-decoration: none;
font-weight: bold;
}
/*******************************************************************
***************************** List styles **************************
********************************************************************/
article ul {
margin-bottom: 1.7em;
}
article li {
padding-bottom: 5px;
}
/*******************************************************************
********************** Navigation sidebar styles *******************
********************************************************************/
nav {
position: fixed;
top: 165px;
bottom: 0;
left: 0;
right: 0;
width: 305px;
border-right: 1px solid #ccc;
overflow-y: scroll;
padding-left: 20px;
padding-right: 20px;
box-sizing: border-box;
}
nav #nav-search {
width: 210px;
height: 30px;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
margin-right: 20px;
margin-top: 20px;
}
.nav-header {
position: fixed;
top: 0;
left: 0;
height: 165px;
width: 305px;
background-color: #00B4EF;
vertical-align: middle;
text-align: center;
margin-top: 0px;
}
.nav-header p {
padding-top: 15px;
}
nav h3 {
font-family: "Proxima Nova", sans-serif;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
nav ul {
font-size: 0.9rem;
padding-left: 15px;
margin: 0;
list-style: none;
}
nav ul a, nav ul a:visited, nav ul a:active {
color: #a1a1a1;
}
nav ul ul {
padding-left: 15px;
margin: 0;
list-style: none;
}
nav ul ul li:first-child
{
padding-top: 0;
}
nav li
{
margin-top: 3px;
}
nav a:hover {
font-weight: bold;
text-decoration: none;
}
nav h2 {
margin: 0;
padding: 0;
}
nav > h2 > a {
display: block;
margin: 10px 0 -10px;
color: #606 !important;
}
/* open */
.nav-trigger:checked + label:not(.steps) .navicon:before,
.nav-trigger:checked + label:not(.steps) .navicon:after {
top: 0 !important;
}
.nav-trigger:checked + label .navicon:before,
.nav-trigger:checked + label .navicon:after {
transition: 0.5s;
}
/* Minus */
.nav-trigger:checked + label {
-webkit-transform: scale(0.75);
transform: scale(0.75);
}
/* × and + */
.nav-trigger:checked + label.plus .navicon,
.nav-trigger:checked + label.x .navicon {
background: transparent;
}
.nav-trigger:checked + label.plus .navicon:before,
.nav-trigger:checked + label.x .navicon:before {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
background: #FFF;
}
.nav-trigger:checked + label.plus .navicon:after,
.nav-trigger:checked + label.x .navicon:after {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
background: #FFF;
}
.nav-trigger:checked + label.plus {
-webkit-transform: scale(0.75) rotate(45deg);
transform: scale(0.75) rotate(45deg);
}
.nav-trigger:checked ~ nav {
left: 0 !important;
}
.nav-trigger:checked ~ .overlay {
display: block;
}
.nav-trigger {
position: fixed;
top: 0;
clip: rect(0, 0, 0, 0);
}
/********************************************************************
***************************** Search styles **************************
*********************************************************************/
.search-input
{
font-family: 'Proxima Nova', sans-serif;
font-size: 0.9rem;
border: 1px solid #ddd;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06);
border-radius: 0.1875rem;
color: #3A3F3E;
width: 75%;
padding: 0.425rem;
}
/********************************************************************
***************************** Code styles ***************************
*********************************************************************/
tt, code, kbd, samp {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 0.8rem;
}
.name, .signature {
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 0.8rem;
}
img {
max-width: 100%;
}
p, ul, ol, blockquote {
margin-bottom: 1em;
}
.class-description {
font-size: 130%;
line-height: 140%;
margin-bottom: 1em;
margin-top: 1em;
}
.class-description:empty {
margin: 0
}
#main {
margin-left: 350px;
margin-right: 50px;
}
header {
display: block;
padding: 0px 4px;
}
.apiLinks
{
display: block;
text-align: center;
font-size: 90%;
margin-top: -20px;
}
.variation {
display: none
}
.signature-attributes {
font-size: 60%;
color: #808080;
font-style: italic;
font-weight: lighter;
}
.container-overview {
margin-top: 25px;
}
.ancestors {
color: #999
}
.ancestors a {
color: #999 !important;
}
.availableIn
{
font-size: 0.8rem;
}
.clear {
clear: both
}
.important {
font-weight: bold;
color: #950B02;
}
.yes-def {
text-indent: -1000px
}
.type-signature {
display: none;
}
.type-returns {
color: #aaa;
}
.member
{
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 16px;
}
.details {
margin-top: 6px;
border-left: 2px solid #DDD;
line-height: 20px;
font-size: 14px;
}
.details dt {
width: auto;
float: left;
padding-left: 10px;
}
.details dd {
margin-left: 70px;
margin-top: 6px;
margin-bottom: 6px;
}
.details ul {
margin: 0
}
.details ul {
list-style-type: none
}
.details pre.prettyprint {
margin: 0
}
.details .object-value {
padding-top: 0
}
.description {
margin-bottom: 1em;
margin-top: 1em;
}
.code-caption {
font-style: italic;
font-size: 107%;
margin: 0;
}
.prettyprint
{
border: 1px solid #ddd;
overflow: auto;
}
.prettyprint.source {
width: inherit;
}
.prettyprint code
{
font-size: 0.65rem;
line-height: 18px;
display: block;
padding: 4px 12px;
margin: 0;
background-color: #fff;
color: #4D4E53;
}
.prettyprint code span.line
{
display: inline-block;
}
.prettyprint.linenums
{
padding-left: 70px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.prettyprint.linenums ol
{
padding-left: 0;
}
.prettyprint.linenums li
{
border-left: 3px #ddd solid;
}
.prettyprint.linenums li.selected,
.prettyprint.linenums li.selected *
{
background-color: lightyellow;
}
.prettyprint.linenums li *
{
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}
.params code {
white-space: pre;
}
.params .name, .props .name, .name code {
color: #4D4E53;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 100%;
}
.params td.description > p:first-child, .props td.description > p:first-child {
margin-top: 0;
padding-top: 0;
}
.params td.description > p:last-child, .props td.description > p:last-child {
margin-bottom: 0;
padding-bottom: 0;
}
span.param-type, .params td .param-type, .param-type dd {
color: #606;
font-family: Consolas, Monaco, 'Andale Mono', monospace
}
.param-type dt, .param-type dd {
display: inline-block
}
.param-type {
margin: 14px 0;
}
.disabled {
color: #454545
}
/* navicon button */
.navicon-button {
display: none;
position: relative;
padding: 2.0625rem 1.5rem;
transition: 0.25s;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
opacity: .8;
}
.navicon-button .navicon:before, .navicon-button .navicon:after {
transition: 0.25s;
}
.navicon-button:hover {
transition: 0.5s;
opacity: 1;
}
.navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after {
transition: 0.25s;
}
.navicon-button:hover .navicon:before {
top: .825rem;
}
.navicon-button:hover .navicon:after {
top: -.825rem;
}
/* navicon */
.navicon {
position: relative;
width: 2.5em;
height: .3125rem;
background: #000;
transition: 0.3s;
border-radius: 2.5rem;
}
.navicon:before, .navicon:after {
display: block;
content: "";
height: .3125rem;
width: 2.5rem;
background: #000;
position: absolute;
z-index: -1;
transition: 0.3s 0.25s;
border-radius: 1rem;
}
.navicon:before {
top: .625rem;
}
.navicon:after {
top: -.625rem;
}
.overlay {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
background: hsla(0, 0%, 0%, 0.5);
z-index: 1;
}
/********************************************************************
**************************** Mobile styles **************************
*********************************************************************/
@media only screen and (min-width: 320px) and (max-width: 680px) {
body {
overflow-x: hidden;
}
nav {
background: #FFF;
width: 250px;
height: 100%;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: -250px;
z-index: 3;
padding: 0 10px;
transition: left 0.2s;
}
.navicon-button {
display: inline-block;
position: fixed;
top: 1.5em;
right: 0;
z-index: 2;
}
#main {
width: 100%;
min-width: 360px;
}
#main section {
padding: 0;
}
footer {
margin-left: 0;
}
}
/** Add a '#' to static members */
[data-type="member"] a::before {
content: '#';
display: inline-block;
margin-left: -14px;
margin-right: 5px;
}
#disqus_thread{
margin-left: 30px;
}

View file

@ -0,0 +1,132 @@
/* Tomorrow Theme */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
/* plain text */
.pln {
color: #4d4d4c; }
@media screen {
/* string content */
.str {
color: #718c00; }
/* a keyword */
.kwd {
color: #8959a8; }
/* a comment */
.com {
color: #8e908c; }
/* a type name */
.typ {
color: #4271ae; }
/* a literal value */
.lit {
color: #f5871f; }
/* punctuation */
.pun {
color: #4d4d4c; }
/* lisp open bracket */
.opn {
color: #4d4d4c; }
/* lisp close bracket */
.clo {
color: #4d4d4c; }
/* a markup tag name */
.tag {
color: #c82829; }
/* a markup attribute name */
.atn {
color: #f5871f; }
/* a markup attribute value */
.atv {
color: #3e999f; }
/* a declaration */
.dec {
color: #f5871f; }
/* a variable name */
.var {
color: #c82829; }
/* a function name */
.fun {
color: #4271ae; } }
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060; }
.kwd {
color: #006;
font-weight: bold; }
.com {
color: #600;
font-style: italic; }
.typ {
color: #404;
font-weight: bold; }
.lit {
color: #044; }
.pun, .opn, .clo {
color: #440; }
.tag {
color: #006;
font-weight: bold; }
.atn {
color: #404; }
.atv {
color: #060; } }
/* Style */
/*
pre.prettyprint {
background: white;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 12px;
line-height: 1.5;
border: 1px solid #ccc;
padding: 10px; }
*/
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0; }
/* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L4,
li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {
/* */ }
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 {
/* */ }

View file

@ -0,0 +1,10 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.augments && data.augments.length) { ?>
<ul><?js data.augments.forEach(function(a) { ?>
<li><?js= self.linkto(a, a) ?></li>
<?js }) ?></ul>
<?js } ?>

View file

@ -0,0 +1,283 @@
<?js
var self = this;
var isGlobalPage;
docs.forEach(function(doc, i) {
?>
<?js
// we only need to check this once
if (typeof isGlobalPage === 'undefined') {
isGlobalPage = (doc.kind === 'globalobj');
}
?>
<?js if (doc.kind === 'mainpage' || (doc.kind === 'package')) { ?>
<?js= self.partial('mainpage.tmpl', doc) ?>
<?js } else if (doc.kind === 'source') { ?>
<?js= self.partial('source.tmpl', doc) ?>
<?js } else { ?>
<div class="apiLinks"> •
<?js
var classes = self.find({kind: 'class', memberof: doc.longname});
if (!isGlobalPage && classes && classes.length) {
?>
<a href="#class">Classes</a> •
<?js } ?>
<?js
var properties = doc.properties;
if (properties && properties.length && properties.forEach) {
?>
<a href="#props">Properties</a> •
<?js } ?>
<?js
var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (methods && methods.length && methods.forEach) {
?>
<a href="#method">Methods</a> •
<?js } ?>
<?js
var signals = self.find({kind: 'signal', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (signals && signals.length && signals.forEach) {
?>
<a href="#signal">Signals</a> •
<?js } ?>
<?js
var typedefs = self.find({kind: 'typedef', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (typedefs && typedefs.length && typedefs.forEach) {
?>
<a href="#typeDef">Type Definitions</a> •
<?js } ?>
<?js
var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (methods && methods.length && methods.forEach) {
?>
<a href="#methodDetails">Method Details</a> •
<?js } ?>
<?js
var signals = self.find({kind: 'signal', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (signals && signals.length && signals.forEach) {
?>
<a href="#signalDetails">Signal Details</a> •
<?js } ?>
</div>
<section>
<article>
<div class="container-overview">
<?js if (doc.kind === 'module' && doc.modules) { ?>
<?js if (doc.description) { ?>
<h3>Description</h3>
<p><?js= doc.description ?></p>
<?js } ?>
<?js doc.modules.forEach(function(module) { ?>
<?js= self.partial('methodList.tmpl', module) ?>
<?js }) ?>
<?js } else if (doc.kind === 'class' || (doc.kind === 'namespace' && doc.signature)) { ?>
<h3>Description</h3>
<p><?js= doc.description ?></p>
<table>
<thead>
<tr>
<th class="memberHeading">Constructor</th>
</tr>
</thead>
<tbody>
<tr>
<td><code><?js= (doc.kind === 'class' ? 'new ' : '') + doc.name + (doc.signature || '') ?></code><p />
<?js if (doc.params) { ?>
<h3 class="paramHeading">Parameters</h3>
<?js= self.partial('params.tmpl', doc.params) ?>
<?js } ?>
</tr>
</tbody>
</table>
<?js= self.partial('details.tmpl', doc) ?>
<?js } else { ?>
<h3>Description</h3>
<?js if (doc.description) { ?>
<p><?js= doc.description ?></p>
<?js } ?>
<?js
var classes = self.find({kind: 'class', memberof: doc.longname});
if (!isGlobalPage && classes && classes.length) {
?>
<h3 id="#class">Classes</h3>
<?js classes.forEach(function(c) { ?>
<p><?js= self.linkto(c.longname, c.name) ?></p>
<?js }); ?>
<?js } ?>
<?js= self.partial('details.tmpl', doc) ?>
<?js if (doc.examples && doc.examples.length) { ?>
<h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3>
<?js= self.partial('examples.tmpl', doc.examples) ?>
<?js } ?>
<?js } ?>
</div>
<?js if (doc.augments && doc.augments.length) { ?>
<h3 class="subsection-title">Extends</h3>
<?js= self.partial('augments.tmpl', doc) ?>
<?js } ?>
<?js if (doc.requires && doc.requires.length) { ?>
<h3 class="subsection-title">Requires</h3>
<ul><?js doc.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r, r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js
var interfaces = self.find({kind: 'interface', memberof: doc.longname});
if (!isGlobalPage && interfaces && interfaces.length) {
?>
<h3 class="subsection-title">Interfaces</h3>
<dl><?js interfaces.forEach(function(i) { ?>
<dt><?js= self.linkto(i.longname, i.name) ?></dt>
<dd><?js if (i.summary) { ?><?js= i.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var mixins = self.find({kind: 'mixin', memberof: doc.longname});
if (!isGlobalPage && mixins && mixins.length) {
?>
<h3 class="subsection-title">Mixins</h3>
<dl><?js mixins.forEach(function(m) { ?>
<dt><?js= self.linkto(m.longname, m.name) ?></dt>
<dd><?js if (m.summary) { ?><?js= m.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var namespaces = self.find({kind: 'namespace', memberof: doc.longname});
if (!isGlobalPage && namespaces && namespaces.length) {
?>
<h3 class="subsection-title">Namespaces</h3>
<dl><?js namespaces.forEach(function(n) { ?>
<dt><?js= self.linkto(n.longname, n.name) ?></dt>
<dd><?js if (n.summary) { ?><?js= n.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var members = self.find({kind: 'member', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
// symbols that are assigned to module.exports are not globals, even though they're not a memberof anything
if (isGlobalPage && members && members.length && members.forEach) {
members = members.filter(function(m) {
return m.longname && m.longname.indexOf('module:') !== 0;
});
}
if (members && members.length && members.forEach) {
?>
<h3 class="subsection-title">Members</h3>
<?js members.forEach(function(p) { ?>
<?js= self.partial('members.tmpl', p) ?>
<?js }); ?>
<?js } ?>
<?js
var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (methods && methods.length && methods.forEach) {
?>
<h3 id="method">Methods</h3>
<table>
<thead>
<tr>
<th class="first">Name</th>
<th class="type">Return Value</th>
<th class="last">Summary</th>
</tr>
</thead>
<tbody>
<?js methods.forEach(function(m) { ?>
<?js= self.partial('methodList.tmpl', m) ?>
<?js }); ?>
</tbody>
</table>
<?js } ?>
<?js
var signals = self.find({kind: 'signal', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (signals && signals.length && signals.forEach) {
?>
<h3 id="signal">Signals</h3>
<table>
<thead>
<tr>
<th class="first">Name</th>
<th class="last">Summary</th>
</tr>
</thead>
<tbody>
<?js signals.forEach(function(m) { ?>
<?js= self.partial('signalList.tmpl', m) ?>
<?js }); ?>
</tbody>
</table>
<?js } ?>
<?js
var typedefs = self.find({kind: 'typedef', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (typedefs && typedefs.length && typedefs.forEach) {
?>
<div class="typeDef">
<h3 id="typeDef">Type Definitions</h3>
<?js typedefs.forEach(function(e) {
if (e.signature) {
?>
<?js= self.partial('members.tmpl', e) ?>
<?js
}
else {
?>
<?js= self.partial('members.tmpl', e) ?>
<?js
}
}); ?>
</div>
<?js } ?>
<?js
var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (methods && methods.length && methods.forEach) {
?>
<div class="methodDetails">
<h3 id="methodDetails">Method Details</h3>
<?js methods.forEach(function(m) { ?>
<?js= self.partial('method.tmpl', m) ?>
<?js }); ?>
<?js } ?>
<?js
var signals = self.find({kind: 'signal', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (signals && signals.length && signals.forEach) {
?>
<div class="methodDetails">
<h3 id="signalDetails">Signal Details</h3>
<?js signals.forEach(function(s) { ?>
<?js= self.partial('signal.tmpl', s) ?>
<?js }); ?>
<?js } ?>
</article>
</section>
<?js } ?>
<?js }); ?>

View file

@ -0,0 +1,143 @@
<?js
var data = obj;
var self = this;
var defaultObjectClass = '';
// Check if the default value is an object or array; if so, apply code highlighting
if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvaluetype === 'array')) {
data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>";
defaultObjectClass = ' class="object-value"';
}
?>
<?js if (data.deprecated) { ?>
<p class="important">Deprecated: <?js
if (data.deprecated === true) { ?>Yes</p><?js }
else { ?><?js= data.deprecated ?></p><?js }
?>
<?js } ?>
<?js
var properties = data.properties;
if (properties && properties.length && properties.forEach && !data.hideconstructor) {
?>
<h3 class="propsHeading" id="props">Properties</h3>
<?js= this.partial('properties.tmpl', data) ?>
<?js } ?>
<?js if (data.version) {?>
<p>Version:</p>
<p><ul class="dummy"><li><?js= version ?></li></ul></p>
<?js } ?>
<?js if (data.since) {?>
<p>Since:</p>
<p><ul class="dummy"><li><?js= since ?></li></ul></p>
<?js } ?>
<?js if (data.inherited && data.inherits && !data.overrides) { ?>
<p>Inherited From:</p>
<p><ul class="dummy"><li>
<?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?>
</li></ul></p>
<?js } ?>
<?js if (data.overrides) { ?>
<p>Overrides:</p>
<p><ul class="dummy"><li>
<?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?>
</li></ul></p>
<?js } ?>
<?js if (data.implementations && data.implementations.length) { ?>
<p>Implementations:</p>
<p><ul>
<?js data.implementations.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></p>
<?js } ?>
<?js if (data.implements && data.implements.length) { ?>
<p>Implements:</p>
<p><ul>
<?js data.implements.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></p>
<?js } ?>
<?js if (data.mixes && data.mixes.length) { ?>
<p>Mixes In:</p>
<p><ul>
<?js data.mixes.forEach(function(a) { ?>
<li><?js= self.linkto(a, a) ?></li>
<?js }); ?>
</ul></p>
<?js } ?>
<?js if (data.author && author.length) {?>
<p>Author:</p>
<p>
<ul><?js author.forEach(function(a) { ?>
<li><?js= self.resolveAuthorLinks(a) ?></li>
<?js }); ?></ul>
</p>
<?js } ?>
<?js if (data.copyright) {?>
<p>Copyright:</p>
<p><ul class="dummy"><li><?js= copyright ?></li></ul></p>
<?js } ?>
<?js if (data.license) {?>
<p>License:</p>
<p><ul class="dummy"><li><?js= license ?></li></ul></p>
<?js } ?>
<?js if (data.defaultvalue) {?>
<p>Default Value:</p>
<p><ul class="dummy">
<li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li>
</ul></p>
<?js } ?>
<?js if (data.meta && self.outputSourceFiles) {?>
<p>Source:</p>
<p><ul class="dummy"><li>
<?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?>
</li></ul></p>
<?js } ?>
<?js if (data.tutorials && tutorials.length) {?>
<p>Tutorials:</p>
<p>
<ul><?js tutorials.forEach(function(t) { ?>
<li><?js= self.tutoriallink(t) ?></li>
<?js }); ?></ul>
</p>
<?js } ?>
<?js if (data.see && see.length) {?>
<p class="see">See:</p>
<p>
<ul><?js see.forEach(function(s) { ?>
<li><?js= self.linkto(s) ?></li>
<?js }); ?></ul>
</p>
<?js } ?>
<?js if (data.todo && todo.length) {?>
<p>To Do:</p>
<p>
<ul><?js todo.forEach(function(t) { ?>
<li><?js= t ?></li>
<?js }); ?></ul>
</p>
<?js } ?>

View file

@ -0,0 +1,141 @@
<?js
var data = obj;
var self = this;
var defaultObjectClass = '';
// Check if the default value is an object or array; if so, apply code highlighting
if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvaluetype === 'array')) {
data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>";
defaultObjectClass = ' class="object-value"';
}
?>
<?js
var properties = data.properties;
if (properties && properties.length && properties.forEach && !data.hideconstructor) {
?>
<?js if (data.deprecated) { ?>
<p class="important">Deprecated: <?js
if (data.deprecated === true) { ?>Yes</p><?js }
else { ?><?js= data.deprecated ?></p><?js }
?>
<?js } ?>
<h3 class="propsHeading" id="props">Properties</h3>
<?js= this.partial('properties.tmpl', data) ?>
<?js } ?>
<?js if (data.version) {?>
<p>Version:</p>
<p><ul class="dummy"><li><?js= version ?></li></ul></p>
<?js } ?>
<?js if (data.since) {?>
<p>Since:</p>
<p><ul class="dummy"><li><?js= since ?></li></ul></p>
<?js } ?>
<?js if (data.inherited && data.inherits && !data.overrides) { ?>
<p>Inherited From:</p>
<p><ul class="dummy"><li>
<?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?>
</li></ul></p>
<?js } ?>
<?js if (data.overrides) { ?>
<p>Overrides:</p>
<p><ul class="dummy"><li>
<?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?>
</li></ul></p>
<?js } ?>
<?js if (data.implementations && data.implementations.length) { ?>
<p>Implementations:</p>
<p><ul>
<?js data.implementations.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></p>
<?js } ?>
<?js if (data.implements && data.implements.length) { ?>
<p>Implements:</p>
<p><ul>
<?js data.implements.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></p>
<?js } ?>
<?js if (data.mixes && data.mixes.length) { ?>
<p>Mixes In:</p>
<p><ul>
<?js data.mixes.forEach(function(a) { ?>
<li><?js= self.linkto(a, a) ?></li>
<?js }); ?>
</ul></p>
<?js } ?>
<?js if (data.author && author.length) {?>
<p>Author:</p>
<p>
<ul><?js author.forEach(function(a) { ?>
<li><?js= self.resolveAuthorLinks(a) ?></li>
<?js }); ?></ul>
</p>
<?js } ?>
<?js if (data.copyright) {?>
<p>Copyright:</p>
<p><ul class="dummy"><li><?js= copyright ?></li></ul></p>
<?js } ?>
<?js if (data.license) {?>
<p>License:</p>
<p><ul class="dummy"><li><?js= license ?></li></ul></p>
<?js } ?>
<?js if (data.defaultvalue) {?>
<p>Default Value:</p>
<p><ul class="dummy">
<li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li>
</ul></p>
<?js } ?>
<?js if (data.meta && self.outputSourceFiles) {?>
<p>Source:</p>
<p><ul class="dummy"><li>
<?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?>
</li></ul></p>
<?js } ?>
<?js if (data.tutorials && tutorials.length) {?>
<p>Tutorials:</p>
<p>
<ul><?js tutorials.forEach(function(t) { ?>
<li><?js= self.tutoriallink(t) ?></li>
<?js }); ?></ul>
</p>
<?js } ?>
<?js if (data.see && see.length) {?>
<p class="see">See:</p>
<p>
<ul><?js see.forEach(function(s) { ?>
<li><?js= self.linkto(s) ?></li>
<?js }); ?></ul>
</p>
<?js } ?>
<?js if (data.todo && todo.length) {?>
<p>To Do:</p>
<p>
<ul><?js todo.forEach(function(t) { ?>
<li><?js= t ?></li>
<?js }); ?></ul>
</p>
<?js } ?>

View file

@ -0,0 +1,13 @@
<?js
var data = obj;
var self = this;
data.forEach(function(example) {
if (example.caption) {
?>
<p class="code-caption"><?js= example.caption ?></p>
<?js } ?>
<pre class="prettyprint"><code><?js= self.htmlsafe(example.code) ?></code></pre>
<?js
});
?>

View file

@ -0,0 +1,32 @@
<?js
var data = obj;
?>
<?js if (data.description && data.type && data.type.names) { ?>
<dl>
<dt>
<div class="param-desc">
<?js= data.description ?>
</div>
</dt>
<dd></dd>
<dt>
<dl class="param-type">
<dt>
Type
</dt>
<dd>
<?js= this.partial('type.tmpl', data.type.names) ?>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
<?js } else { ?>
<div class="param-desc">
<?js if (data.description) { ?>
<?js= data.description ?>
<?js } else if (data.type && data.type.names) { ?>
<?js= this.partial('type.tmpl', data.type.names) ?>
<?js } ?>
</div>
<?js } ?>

View file

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<?js if (!env.conf.docdash) { env.conf.docdash = {};} ?>
<meta charset="utf-8">
<title><?js= title ?></title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
</head>
<body>
<div class="nav-header">
<p><img src="images/white-logo.png" width="200px" /></p>
<?js if (env.conf.docdash.search) { ?>
<input type="text" class="search-input" id="nav-search" placeholder="Search ..." />
<?js } ?>
</div>
<nav>
<?js= this.nav ?>
</nav>
<div id="main">
<h1 class="page-title"><?js= title ?></h1>
<?js= content ?>
<?js if (env.conf.docdash.disqus) { ?>
<div id="disqus_thread"></div>
<script>
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = '//<?js= env.conf.docdash.disqus ?>.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<?js } ?>
</div>
<br class="clear">
<script>prettyPrint();</script>
<script src="scripts/linenumber.js"></script>
<?js if (env.conf.docdash.search || env.conf.docdash.collapse) { ?>
<script src="scripts/jquery-3.1.1.min.js"></script>
<?js if (env.conf.docdash.search) { ?>
<script src="scripts/search.js"></script>
<?js } ?>
<?js if (env.conf.docdash.collapse) { ?>
<script src="scripts/collapse.js"></script>
<?js } ?>
<?js } ?>
<?js if (env.conf.docdash.scripts && env.conf.docdash.scripts.length) {
for(var i = 0; i < env.conf.docdash.scripts.length; i++) {
if (env.conf.docdash.scripts[i].indexOf(".css") != -1) { ?>
<link type="text/css" rel="stylesheet" href="<?js= env.conf.docdash.scripts[i] ?>">
<?js } else { ?>
<script src="<?js= env.conf.docdash.scripts[i] ?>"></script>
<?js } ?>
<?js } ?>
<?js } ?>
</body>
</html>

View file

@ -0,0 +1,10 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.readme) { ?>
<section class="readme">
<article><?js= data.readme ?></article>
</section>
<?js } ?>

View file

@ -0,0 +1,41 @@
<?js
var data = obj;
var self = this;
?>
<table>
<thead>
<tr>
<th>
<span id="<?js= id ?>" class="member"><?js= data.attribs + name + (data.signature ? data.signature : '') ?></span><br />
Type: <?js= self.partial('type.tmpl', data.type.names) ?>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<?js if (data.description) { ?>
<p><?js= data.description ?></p>
<?js } else { ?>
<p style="color:red;">&nbsp;</p>
<?js } ?>
<?js= self.partial('details.tmpl', data) ?>
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>
</td>
</tr>
</tbody>
</table>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>

View file

@ -0,0 +1,119 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.kind !== 'module' && !data.hideconstructor) { ?>
<table>
<thead>
<tr>
<th>
<span id="<?js= id ?>" class="member"><?js= data.attribs + (kind === 'class' ? 'new ' : '') + name + (data.signature || '') ?></span>
<?js if (data.returns && returns.length) { ?><br />
Returns: <span style="font-weight: normal;">
<?js returns.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} ?></span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<?js if (data.kind !== 'module' && data.description && !data.hideconstructor) { ?>
<p>
<?js= data.description ?>
<?js= this.partial('details.tmpl', data) ?>
</p>
<?js } else { ?>
<p style="color:red;">&nbsp;</p>
<?js } ?>
<?js if (data.exceptions && exceptions.length) { ?>
<h3 class="subHeading">Throws:</h3>
<?js if (exceptions.length > 1) { ?><ul><?js
exceptions.forEach(function(r) { ?>
<li><?js= self.partial('exceptions.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
exceptions.forEach(function(r) { ?>
<p><?js= self.partial('exceptions.tmpl', r) ?></p>
<?js });
} } ?>
<?js if (data.params && params.length && !data.hideconstructor) { ?>
<h3 class="subHeading">Parameters</h3>
<?js= this.partial('params.tmpl', params) ?>
<?js } ?>
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>
</td>
</tr>
</tbody>
</table>
<?js } ?>
<?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?>
<h5>Extends:</h5>
<?js= self.partial('augments.tmpl', data) ?>
<?js } ?>
<?js if (kind === 'event' && data.type && data.type.names) {?>
<h5>Type:</h5>
<ul>
<li>
<?js= self.partial('type.tmpl', data.type.names) ?>
</li>
</ul>
<?js } ?>
<?js if (data['this']) { ?>
<h5>This:</h5>
<ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
<?js } ?>
<?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?>
<h5>Requires:</h5>
<ul><?js data.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listens && listens.length) { ?>
<h5>Listens to Events:</h5>
<ul><?js listens.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listeners && listeners.length) { ?>
<h5>Listeners of This Event:</h5>
<ul><?js listeners.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.yields && yields.length) { ?>
<h5>Yields:</h5>
<?js if (yields.length > 1) { ?><ul><?js
yields.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
yields.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} } ?>

View file

@ -0,0 +1,107 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.kind !== 'module' && !data.hideconstructor) { ?>
<?js if (data.kind === 'class' && data.classdesc) { ?>
<h2>Constructor</h2>
<?js } ?>
<?js if (data.kind !== 'namespace') { ?>
<tr>
<td><a href="#<?js= id ?>">
<code><?js= (kind === 'class' ? 'new ' : '') + name + (data.signatureHead || '') ?></code></a>
</td>
<td>
<?js if (!data.returns) { ?>
None
<?js } else if (data.returns && returns.length) { ?>
<?js if (returns.length > 1) { ?><ul><?js
returns.forEach(function(r) { ?>
<li><?js= self.partial('returnsSimp.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
returns.forEach(function(r) { ?>
<?js= self.partial('returnsSimp.tmpl', r) ?>
<?js });
} ?>
<?js } ?>
</td>
<td>
<?js if (data.description) { ?>
<?js= description ?>
<?js= this.partial('details.tmpl', data) ?>
<?js } else { ?>
<?js= this.partial('details.tmpl', data) ?>
<?js } ?>
</td>
</tr>
<?js } ?>
<?js } ?>
<?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?>
<h5>Extends:</h5>
<?js= self.partial('augments.tmpl', data) ?>
<?js } ?>
<?js if (kind === 'event' && data.type && data.type.names) {?>
<h5>Type:</h5>
<ul>
<li>
<?js= self.partial('type.tmpl', data.type.names) ?>
</li>
</ul>
<?js } ?>
<?js if (data['this']) { ?>
<h5>This:</h5>
<ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
<?js } ?>
<?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?>
<h5>Requires:</h5>
<ul><?js data.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listens && listens.length) { ?>
<h5>Listens to Events:</h5>
<ul><?js listens.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listeners && listeners.length) { ?>
<h5>Listeners of This Event:</h5>
<ul><?js listeners.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.yields && yields.length) { ?>
<h5>Yields:</h5>
<?js if (yields.length > 1) { ?><ul><?js
yields.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
yields.forEach(function(r) { ?>
<?js= self.partial('returnsSimp.tmpl', r) ?>
<?js });
} } ?>
<!--
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>
-->

View file

@ -0,0 +1,67 @@
<?js
var params = obj;
/* sort subparams under their parent params (like opts.classname) */
var parentParam = null;
params.forEach(function(param, i) {
var paramRegExp;
if (!param) {
return;
}
if (parentParam && parentParam.name && param.name) {
try {
paramRegExp = new RegExp('^(?:' + parentParam.name + '(?:\\[\\])*)\\.(.+)$');
}
catch (e) {
// there's probably a typo in the JSDoc comment that resulted in a weird
// parameter name
return;
}
if ( paramRegExp.test(param.name) ) {
param.name = RegExp.$1;
parentParam.subparams = parentParam.subparams || [];
parentParam.subparams.push(param);
params[i] = null;
}
else {
parentParam = param;
}
}
else {
parentParam = param;
}
});
/* determine if we need extra columns, "attributes" and "default" */
params.hasAttributes = false;
params.hasDefault = false;
params.hasName = false;
params.forEach(function(param) {
if (!param) { return; }
if (param.optional || param.nullable || param.variable) {
params.hasAttributes = true;
}
if (param.name) {
params.hasName = true;
}
if (typeof param.defaultvalue !== 'undefined') {
params.hasDefault = true;
}
});
?>
<?js params.forEach(function(param, i, arr) { ?>
<?js if (i === arr.length - 1) { ?>
<?js= param.name ?>
<?js } else { ?>
<span><?js= param.name ?>, </span>
<?js } ?>
<?js }); ?>

View file

@ -0,0 +1,115 @@
<?js
var params = obj;
/* sort subparams under their parent params (like opts.classname) */
var parentParam = null;
params.forEach(function(param, i) {
var paramRegExp;
if (!param) {
return;
}
if (parentParam && parentParam.name && param.name) {
try {
paramRegExp = new RegExp('^(?:' + parentParam.name + '(?:\\[\\])*)\\.(.+)$');
}
catch (e) {
// there's probably a typo in the JSDoc comment that resulted in a weird
// parameter name
return;
}
if ( paramRegExp.test(param.name) ) {
param.name = RegExp.$1;
parentParam.subparams = parentParam.subparams || [];
parentParam.subparams.push(param);
params[i] = null;
}
else {
parentParam = param;
}
}
else {
parentParam = param;
}
});
/* determine if we need extra columns, "attributes" and "default" */
params.hasAttributes = false;
params.hasDefault = false;
params.hasName = false;
params.forEach(function(param) {
if (!param) { return; }
if (param.optional || param.nullable || param.variable) {
params.hasAttributes = true;
}
if (param.name) {
params.hasName = true;
}
if (typeof param.defaultvalue !== 'undefined') {
params.hasDefault = true;
}
});
?>
<table class="params">
<thead>
<tr>
<?js if (params.hasName) {?>
<th>Name</th>
<?js } ?>
<th>Type</th>
<?js if (params.hasAttributes) {?>
<th>Attributes</th>
<?js } ?>
<?js if (params.hasDefault) {?>
<th>Default</th>
<?js } ?>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<?js
var self = this;
params.forEach(function(param) {
if (!param) { return; }
?>
<tr>
<?js if (params.hasName) {?>
<td class="name"><code><?js= param.name ?></code></td>
<?js } ?>
<td class="type">
<?js if (param.type && param.type.names) {?>
<?js= self.partial('type.tmpl', param.type.names) ?>
<?js } ?>
</td>
<?js if (params.hasDefault) {?>
<td class="default">
<?js if (typeof param.defaultvalue !== 'undefined') { ?>
Default Value: <?js= self.htmlsafe(param.defaultvalue) ?>
<?js } ?>
</td>
<?js } ?>
<td class="description last"><?js= param.description ?><?js if (param.subparams) { ?>
<h6>Properties</h6>
<?js= self.partial('params.tmpl', param.subparams) ?>
<?js } ?></td>
</tr>
<?js }); ?>
</tbody>
</table>

View file

@ -0,0 +1,103 @@
<?js
var data = obj;
var props = data.subprops || data.properties;
/* sort subprops under their parent props (like opts.classname) */
var parentProp = null;
props.forEach(function(prop, i) {
if (!prop) { return; }
if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) {
prop.name = prop.name.substr(parentProp.name.length+1);
parentProp.subprops = parentProp.subprops || [];
parentProp.subprops.push(prop);
props[i] = null;
}
else {
parentProp = prop;
}
});
/* determine if we need extra columns, "attributes" and "default" */
props.hasAttributes = false;
props.hasDefault = false;
props.hasName = false;
props.forEach(function(prop) {
if (!prop) { return; }
if (prop.optional || prop.nullable) {
props.hasAttributes = true;
}
if (prop.name) {
props.hasName = true;
}
if (typeof prop.defaultvalue !== 'undefined' && !data.isEnum) {
props.hasDefault = true;
}
});
?>
<table class="props">
<thead>
<tr>
<?js if (props.hasName) {?>
<th class="first">Name</th>
<?js } ?>
<th class="type">Type</th>
<?js if (props.hasAttributes) {?>
<th>Attributes</th>
<?js } ?>
<th class="last">Summary</th>
</tr>
</thead>
<tbody>
<?js
var self = this;
props.forEach(function(prop) {
if (!prop) { return; }
?>
<tr>
<?js if (props.hasName) {?>
<td><span class="signature"><?js= prop.name ?></span></td>
<?js } ?>
<td class="type">
<?js if (prop.type && prop.type.names) {?>
<?js= self.partial('type.tmpl', prop.type.names) ?>
<?js } ?>
</td>
<?js if (props.hasAttributes) {?>
<td class="attributes">
<?js if (prop.optional) { ?>
&lt;optional><br>
<?js } ?>
<?js if (prop.nullable) { ?>
&lt;nullable><br>
<?js } ?>
</td>
<?js } ?>
<td class="description last">
<?js= prop.description ?>
<?js if (props.hasDefault) {?>
<?js if (typeof prop.defaultvalue !== 'undefined') { ?>
<p><b>Default Value:</b> <?js= self.htmlsafe(prop.defaultvalue) ?> </p>
<?js } ?>
<?js } ?>
<?js if (prop.subprops) { ?>
<h6>Properties</h6><?js= self.partial('properties.tmpl', prop) ?>
<?js } ?>
</td>
</tr>
<?js }); ?>
</tbody>
</table>

View file

@ -0,0 +1,8 @@
<?js
var data = obj || {};
if (data.description) {
?>
<?js= description ?>
<?js } else { ?>
<?js= this.partial('type.tmpl', data.type.names) ?>
<?js } ?>

View file

@ -0,0 +1,6 @@
<?js
var data = obj || {}; ?>
<?js if (data.type && data.type.names) {?>
<?js= this.partial('type.tmpl', data.type.names) ?>
<?js } ?>

View file

@ -0,0 +1,123 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.kind !== 'module' && !data.hideconstructor) { ?>
<table>
<thead>
<tr>
<th>
<span id="<?js= id ?>" class="member"><?js= name ?>(
<?js if (data.params) { ?>
<?js= self.partial('paramList.tmpl', params) ?>
<?js } ?>
)</span>
<?js if (data.returns && returns.length) { ?><br />
Returns: <span style="font-weight: normal;">
<?js returns.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} ?></span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<?js if (data.kind !== 'module' && data.description && !data.hideconstructor) { ?>
<p>
<?js= data.description ?>
<?js= this.partial('details.tmpl', data) ?>
</p>
<?js } else { ?>
<p style="color:red;">&nbsp;</p>
<?js } ?>
<?js if (data.exceptions && exceptions.length) { ?>
<h3 class="subHeading">Throws:</h3>
<?js if (exceptions.length > 1) { ?><ul><?js
exceptions.forEach(function(r) { ?>
<li><?js= self.partial('exceptions.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
exceptions.forEach(function(r) { ?>
<p><?js= self.partial('exceptions.tmpl', r) ?></p>
<?js });
} } ?>
<?js if (data.params && params.length && !data.hideconstructor) { ?>
<h3 class="subHeading">Parameters</h3>
<?js= this.partial('params.tmpl', params) ?>
<?js } ?>
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>
</td>
</tr>
</tbody>
</table>
<?js } ?>
<?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?>
<h5>Extends:</h5>
<?js= self.partial('augments.tmpl', data) ?>
<?js } ?>
<?js if (kind === 'event' && data.type && data.type.names) {?>
<h5>Type:</h5>
<ul>
<li>
<?js= self.partial('type.tmpl', data.type.names) ?>
</li>
</ul>
<?js } ?>
<?js if (data['this']) { ?>
<h5>This:</h5>
<ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
<?js } ?>
<?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?>
<h5>Requires:</h5>
<ul><?js data.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listens && listens.length) { ?>
<h5>Listens to Events:</h5>
<ul><?js listens.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listeners && listeners.length) { ?>
<h5>Listeners of This Event:</h5>
<ul><?js listeners.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.yields && yields.length) { ?>
<h5>Yields:</h5>
<?js if (yields.length > 1) { ?><ul><?js
yields.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
yields.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} } ?>

View file

@ -0,0 +1,92 @@
<?js
var data = obj;
var self = this;
?>
<?js if (data.kind !== 'module' && !data.hideconstructor) { ?>
<?js if (data.kind === 'class' && data.classdesc) { ?>
<h2>Constructor</h2>
<?js } ?>
<?js if (data.kind !== 'namespace') { ?>
<tr>
<td><a href="#<?js= id ?>">
<code><?js= (kind === 'class' ? 'new ' : '') + name + (data.signatureHead || '') ?></code></a>
</td>
<td>
<?js if (data.summary) { ?>
<?js= summary ?>
<?js= this.partial('details.tmpl', data) ?>
<?js } else { ?>
<?js= this.partial('details.tmpl', data) ?>
<?js } ?>
</td>
</tr>
<?js } ?>
<?js } ?>
<?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?>
<h5>Extends:</h5>
<?js= self.partial('augments.tmpl', data) ?>
<?js } ?>
<?js if (kind === 'event' && data.type && data.type.names) {?>
<h5>Type:</h5>
<ul>
<li>
<?js= self.partial('type.tmpl', data.type.names) ?>
</li>
</ul>
<?js } ?>
<?js if (data['this']) { ?>
<h5>This:</h5>
<ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
<?js } ?>
<?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?>
<h5>Requires:</h5>
<ul><?js data.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listens && listens.length) { ?>
<h5>Listens to Events:</h5>
<ul><?js listens.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listeners && listeners.length) { ?>
<h5>Listeners of This Event:</h5>
<ul><?js listeners.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.yields && yields.length) { ?>
<h5>Yields:</h5>
<?js if (yields.length > 1) { ?><ul><?js
yields.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
yields.forEach(function(r) { ?>
<?js= self.partial('returnsSimp.tmpl', r) ?>
<?js });
} } ?>
<!--
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>
-->

View file

@ -0,0 +1,8 @@
<?js
var data = obj;
?>
<section>
<article>
<pre class="prettyprint source linenums"><code><?js= data.code ?></code></pre>
</article>
</section>

View file

@ -0,0 +1,19 @@
<section>
<header>
<?js if (children.length > 0) { ?>
<ul><?js
var self = this;
children.forEach(function(t) { ?>
<li><?js= self.tutoriallink(t.name) ?></li>
<?js }); ?></ul>
<?js } ?>
<h2><?js= header ?></h2>
</header>
<article>
<?js= content ?>
</article>
</section>

View file

@ -0,0 +1,7 @@
<?js
var data = obj;
var self = this;
data.forEach(function(name, i) { ?>
<?js= self.linkto(name, self.htmlsafe(name)) ?>
<?js if (i < data.length-1) { ?>|<?js } ?>
<?js }); ?>

View file

@ -107,9 +107,6 @@ exports.handlers = {
if (e.doclet.hifiClientEntity) {
rows.push("Client Entity Scripts");
}
if (e.doclet.hifiAvatar) {
rows.push("Avatar Scripts");
}
if (e.doclet.hifiServerEntity) {
rows.push("Server Entity Scripts");
}
@ -117,15 +114,30 @@ exports.handlers = {
rows.push("Assignment Client Scripts");
}
// Append an Available In: table at the end of the namespace description.
// Append an Available In: sentence at the beginning of the namespace description.
if (rows.length > 0) {
var table = "<table><tr><th>Available in:</th><td>" + rows.join("</td><td>") + "</td></tr></table><br>";
e.doclet.description = table + (e.doclet.description ? e.doclet.description : "");
}
var availableIn = "<p class='availableIn'><b>Supported Script Types:</b> " + rows.join(" &bull; ") + "</p>";
e.doclet.description = (e.doclet.description ? e.doclet.description : "") + availableIn;
}
}
}
};
// Functions for adding @signal custom tag
/** @private */
function setDocletKindToTitle(doclet, tag) {
doclet.addTag( 'kind', tag.title );
}
function setDocletNameToValue(doclet, tag) {
if (tag.value && tag.value.description) { // as in a long tag
doclet.addTag('name', tag.value.description);
} else if (tag.text) { // or a short tag
doclet.addTag('name', tag.text);
}
}
// Define custom hifi tags here
exports.defineTags = function (dictionary) {
@ -143,14 +155,6 @@ exports.defineTags = function (dictionary) {
}
});
// @hifi-avatar-script
dictionary.defineTag("hifi-avatar", {
onTagged: function (doclet, tag) {
doclet.hifiAvatar = true;
}
});
// @hifi-client-entity
dictionary.defineTag("hifi-client-entity", {
onTagged: function (doclet, tag) {
@ -164,4 +168,14 @@ exports.defineTags = function (dictionary) {
doclet.hifiServerEntity = true;
}
});
// @signal
dictionary.defineTag("signal", {
mustHaveValue: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
}
});
};

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 02111c50e71dd664da8ad5c6a6eca767
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -14,12 +14,14 @@ using System.Collections.Generic;
class AvatarExporter : MonoBehaviour {
// update version number for every PR that changes this file, also set updated version in README file
static readonly string AVATAR_EXPORTER_VERSION = "0.2";
static readonly string AVATAR_EXPORTER_VERSION = "0.3.1";
static readonly float HIPS_GROUND_MIN_Y = 0.01f;
static readonly float HIPS_SPINE_CHEST_MIN_SEPARATION = 0.001f;
static readonly int MAXIMUM_USER_BONE_COUNT = 256;
static readonly string EMPTY_WARNING_TEXT = "None";
static readonly string TEXTURES_DIRECTORY = "textures";
static readonly string DEFAULT_MATERIAL_NAME = "No Name";
// TODO: use regex
static readonly string[] RECOMMENDED_UNITY_VERSIONS = new string[] {
@ -195,8 +197,17 @@ class AvatarExporter : MonoBehaviour {
" Thumb Intermediate",
" Thumb Proximal",
};
static readonly string STANDARD_SHADER = "Standard";
static readonly string STANDARD_ROUGHNESS_SHADER = "Standard (Roughness setup)";
static readonly string STANDARD_SPECULAR_SHADER = "Standard (Specular setup)";
static readonly string[] SUPPORTED_SHADERS = new string[] {
STANDARD_SHADER,
STANDARD_ROUGHNESS_SHADER,
STANDARD_SPECULAR_SHADER,
};
enum BoneRule {
enum AvatarRule {
RecommendedUnityVersion,
SingleRoot,
NoDuplicateMapping,
@ -215,14 +226,14 @@ class AvatarExporter : MonoBehaviour {
HipsNotOnGround,
HipsSpineChestNotCoincident,
TotalBoneCountUnderLimit,
BoneRuleEnd,
AvatarRuleEnd,
};
// rules that are treated as errors and prevent exporting, otherwise rules will show as warnings
static readonly BoneRule[] EXPORT_BLOCKING_BONE_RULES = new BoneRule[] {
BoneRule.HipsMapped,
BoneRule.SpineMapped,
BoneRule.ChestMapped,
BoneRule.HeadMapped,
static readonly AvatarRule[] EXPORT_BLOCKING_AVATAR_RULES = new AvatarRule[] {
AvatarRule.HipsMapped,
AvatarRule.SpineMapped,
AvatarRule.ChestMapped,
AvatarRule.HeadMapped,
};
class UserBoneInformation {
@ -255,15 +266,63 @@ class AvatarExporter : MonoBehaviour {
}
}
static Dictionary<string, UserBoneInformation> userBoneInfos = new Dictionary<string, UserBoneInformation>();
static Dictionary<string, string> humanoidToUserBoneMappings = new Dictionary<string, string>();
static BoneTreeNode userBoneTree = new BoneTreeNode();
static Dictionary<BoneRule, string> failedBoneRules = new Dictionary<BoneRule, string>();
class MaterialData {
public Color albedo;
public string albedoMap;
public double metallic;
public string metallicMap;
public double roughness;
public string roughnessMap;
public string normalMap;
public string occlusionMap;
public Color emissive;
public string emissiveMap;
public string getJSON() {
string json = "{ \"materialVersion\": 1, \"materials\": { ";
json += "\"albedo\": [" + albedo.r + ", " + albedo.g + ", " + albedo.b + "], ";
if (!string.IsNullOrEmpty(albedoMap)) {
json += "\"albedoMap\": \"" + albedoMap + "\", ";
}
json += "\"metallic\": " + metallic + ", ";
if (!string.IsNullOrEmpty(metallicMap)) {
json += "\"metallicMap\": \"" + metallicMap + "\", ";
}
json += "\"roughness\": " + roughness + ", ";
if (!string.IsNullOrEmpty(roughnessMap)) {
json += "\"roughnessMap\": \"" + roughnessMap + "\", ";
}
if (!string.IsNullOrEmpty(normalMap)) {
json += "\"normalMap\": \"" + normalMap + "\", ";
}
if (!string.IsNullOrEmpty(occlusionMap)) {
json += "\"occlusionMap\": \"" + occlusionMap + "\", ";
}
json += "\"emissive\": [" + emissive.r + ", " + emissive.g + ", " + emissive.b + "] ";
if (!string.IsNullOrEmpty(emissiveMap)) {
json += "\", emissiveMap\": \"" + emissiveMap + "\"";
}
json += "} }";
return json;
}
}
static string assetPath = "";
static string assetName = "";
static ModelImporter modelImporter;
static HumanDescription humanDescription;
static Dictionary<string, string> dependencyTextures = new Dictionary<string, string>();
static Dictionary<string, UserBoneInformation> userBoneInfos = new Dictionary<string, UserBoneInformation>();
static Dictionary<string, string> humanoidToUserBoneMappings = new Dictionary<string, string>();
static BoneTreeNode userBoneTree = new BoneTreeNode();
static Dictionary<AvatarRule, string> failedAvatarRules = new Dictionary<AvatarRule, string>();
static Dictionary<string, string> textureDependencies = new Dictionary<string, string>();
static Dictionary<string, string> materialMappings = new Dictionary<string, string>();
static Dictionary<string, MaterialData> materialDatas = new Dictionary<string, MaterialData>();
static List<string> materialAlternateStandardShader = new List<string>();
static Dictionary<string, string> materialUnsupportedShader = new Dictionary<string, string>();
[MenuItem("High Fidelity/Export New Avatar")]
static void ExportNewAvatar() {
@ -280,7 +339,10 @@ class AvatarExporter : MonoBehaviour {
EditorUtility.DisplayDialog("About", "High Fidelity, Inc.\nAvatar Exporter\nVersion " + AVATAR_EXPORTER_VERSION, "Ok");
}
static void ExportSelectedAvatar(bool updateAvatar) {
static void ExportSelectedAvatar(bool updateAvatar) {
// ensure everything is saved to file before exporting
AssetDatabase.SaveAssets();
string[] guids = Selection.assetGUIDs;
if (guids.Length != 1) {
if (guids.Length == 0) {
@ -292,7 +354,7 @@ class AvatarExporter : MonoBehaviour {
}
assetPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
assetName = Path.GetFileNameWithoutExtension(assetPath);
ModelImporter modelImporter = ModelImporter.GetAtPath(assetPath) as ModelImporter;
modelImporter = ModelImporter.GetAtPath(assetPath) as ModelImporter;
if (Path.GetExtension(assetPath).ToLower() != ".fbx" || modelImporter == null) {
EditorUtility.DisplayDialog("Error", "Please select an .fbx model asset to export.", "Ok");
return;
@ -302,26 +364,34 @@ class AvatarExporter : MonoBehaviour {
" the Rig section of it's Inspector window.", "Ok");
return;
}
humanDescription = modelImporter.humanDescription;
SetUserBoneInformation();
string textureWarnings = SetTextureDependencies();
SetBoneAndMaterialInformation();
// check if we should be substituting a bone for a missing UpperChest mapping
AdjustUpperChestMapping();
// format resulting bone rule failure strings
// consider export-blocking bone rules to be errors and show them in an error dialog,
// and also include any other bone rule failures plus texture warnings as warnings in the dialog
// format resulting avatar rule failure strings
// consider export-blocking avatar rules to be errors and show them in an error dialog,
// and also include any other avatar rule failures plus texture warnings as warnings in the dialog
string boneErrors = "";
string warnings = "";
foreach (var failedBoneRule in failedBoneRules) {
if (Array.IndexOf(EXPORT_BLOCKING_BONE_RULES, failedBoneRule.Key) >= 0) {
boneErrors += failedBoneRule.Value + "\n\n";
foreach (var failedAvatarRule in failedAvatarRules) {
if (Array.IndexOf(EXPORT_BLOCKING_AVATAR_RULES, failedAvatarRule.Key) >= 0) {
boneErrors += failedAvatarRule.Value + "\n\n";
} else {
warnings += failedBoneRule.Value + "\n\n";
warnings += failedAvatarRule.Value + "\n\n";
}
}
foreach (string materialName in materialAlternateStandardShader) {
warnings += "The material " + materialName + " is not using the recommended variation of the Standard shader. " +
"We recommend you change it to Standard (Roughness setup) shader for improved performance.\n\n";
}
foreach (var material in materialUnsupportedShader) {
warnings += "The material " + material.Key + " is using an unsupported shader " + material.Value +
". Please change it to a Standard shader type.\n\n";
}
warnings += textureWarnings;
if (!string.IsNullOrEmpty(boneErrors)) {
// if there are both errors and warnings then warnings will be displayed with errors in the error dialog
@ -334,7 +404,7 @@ class AvatarExporter : MonoBehaviour {
EditorUtility.DisplayDialog("Error", boneErrors, "Ok");
return;
}
string documentsFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
string hifiFolder = documentsFolder + "\\High Fidelity Projects";
if (updateAvatar) { // Update Existing Avatar menu option
@ -408,9 +478,9 @@ class AvatarExporter : MonoBehaviour {
modelImporter.SaveAndReimport();
// redo parent names, joint mappings, and user bone positions due to the fbx change
// as well as re-check the bone rules for failures
// as well as re-check the avatar rules for failures
humanDescription = modelImporter.humanDescription;
SetUserBoneInformation();
SetBoneAndMaterialInformation();
}
}
} else {
@ -456,7 +526,7 @@ class AvatarExporter : MonoBehaviour {
return;
}
// display success dialog with any bone rule warnings
// display success dialog with any avatar rule warnings
string successDialog = "Avatar successfully updated!";
if (!string.IsNullOrEmpty(warnings)) {
successDialog += "\n\nWarnings:\n" + warnings;
@ -575,6 +645,27 @@ class AvatarExporter : MonoBehaviour {
jointOffset.y + ", " + jointOffset.z + ", " + jointOffset.w + ")\n");
}
}
// if there is any material data to save then write out all materials in JSON material format to the materialMap field
if (materialDatas.Count > 0) {
string materialJson = "{ ";
foreach (var materialData in materialDatas) {
// if this is the only material in the mapping and it is the default name No Name mapped to No Name,
// then the avatar has no embedded materials and this material should be applied to all meshes
string materialName = materialData.Key;
if (materialMappings.Count == 1 && materialName == DEFAULT_MATERIAL_NAME &&
materialMappings[materialName] == DEFAULT_MATERIAL_NAME) {
materialJson += "\"all\": ";
} else {
materialJson += "\"mat::" + materialName + "\": ";
}
materialJson += materialData.Value.getJSON();
materialJson += ", ";
}
materialJson = materialJson.Substring(0, materialJson.LastIndexOf(", "));
materialJson += " }";
File.AppendAllText(exportFstPath, "materialMap = " + materialJson);
}
// open File Explorer to the project directory once finished
System.Diagnostics.Process.Start("explorer.exe", "/select," + exportFstPath);
@ -582,11 +673,17 @@ class AvatarExporter : MonoBehaviour {
return true;
}
static void SetUserBoneInformation() {
static void SetBoneAndMaterialInformation() {
userBoneInfos.Clear();
humanoidToUserBoneMappings.Clear();
userBoneTree = new BoneTreeNode();
materialDatas.Clear();
materialAlternateStandardShader.Clear();
materialUnsupportedShader.Clear();
SetMaterialMappings();
// instantiate a game object of the user avatar to traverse the bone tree to gather
// bone parents and positions as well as build a bone tree, then destroy it
UnityEngine.Object avatarResource = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object));
@ -610,32 +707,40 @@ class AvatarExporter : MonoBehaviour {
}
}
// generate the list of bone rule failure strings for any bone rules that are not satisfied by this avatar
SetFailedBoneRules();
// generate the list of avatar rule failure strings for any avatar rules that are not satisfied by this avatar
SetFailedAvatarRules();
}
static void TraverseUserBoneTree(Transform modelBone) {
GameObject gameObject = modelBone.gameObject;
// check if this transform is a node containing mesh, light, or camera instead of a bone
bool mesh = gameObject.GetComponent<MeshRenderer>() != null || gameObject.GetComponent<SkinnedMeshRenderer>() != null;
MeshRenderer meshRenderer = gameObject.GetComponent<MeshRenderer>();
SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
bool mesh = meshRenderer != null || skinnedMeshRenderer != null;
bool light = gameObject.GetComponent<Light>() != null;
bool camera = gameObject.GetComponent<Camera>() != null;
// if it is in fact a bone, add it to the bone tree as well as user bone infos list with position and parent name
if (!mesh && !light && !camera) {
// if this is a mesh and the model is using external materials then store its material data to be exported
if (mesh && modelImporter.materialLocation == ModelImporterMaterialLocation.External) {
Material[] materials = skinnedMeshRenderer != null ? skinnedMeshRenderer.sharedMaterials : meshRenderer.sharedMaterials;
StoreMaterialData(materials);
} else if (!light && !camera) {
// if it is in fact a bone, add it to the bone tree as well as user bone infos list with position and parent name
UserBoneInformation userBoneInfo = new UserBoneInformation();
userBoneInfo.position = modelBone.position; // bone's absolute position
string boneName = modelBone.name;
if (modelBone.parent == null) {
// if no parent then this is actual root bone node of the user avatar, so consider it's parent as "root"
boneName = GetRootBoneName(); // ensure we use the root bone name from the skeleton list for consistency
userBoneTree = new BoneTreeNode(boneName); // initialize root of tree
userBoneInfo.parentName = "root";
userBoneInfo.boneTreeNode = userBoneTree;
} else {
// otherwise add this bone node as a child to it's parent's children list
string parentName = modelBone.parent.name;
// if its a child of the root bone, use the root bone name from the skeleton list as the parent for consistency
string parentName = modelBone.parent.parent == null ? GetRootBoneName() : modelBone.parent.name;
BoneTreeNode boneTreeNode = new BoneTreeNode(boneName);
userBoneInfos[parentName].boneTreeNode.children.Add(boneTreeNode);
userBoneInfo.parentName = parentName;
@ -658,7 +763,7 @@ class AvatarExporter : MonoBehaviour {
}
return result;
}
static void AdjustUpperChestMapping() {
if (!humanoidToUserBoneMappings.ContainsKey("UpperChest")) {
// if parent of Neck is not Chest then map the parent to UpperChest
@ -682,8 +787,16 @@ class AvatarExporter : MonoBehaviour {
}
}
static void SetFailedBoneRules() {
failedBoneRules.Clear();
static string GetRootBoneName() {
// the "root" bone is the first element in the human skeleton bone list
if (humanDescription.skeleton.Length > 0) {
return humanDescription.skeleton[0].name;
}
return "";
}
static void SetFailedAvatarRules() {
failedAvatarRules.Clear();
string hipsUserBone = "";
string spineUserBone = "";
@ -692,60 +805,60 @@ class AvatarExporter : MonoBehaviour {
Vector3 hipsPosition = new Vector3();
// iterate over all bone rules in order and add any rules that fail
// to the failed bone rules map with appropriate error or warning text
for (BoneRule boneRule = 0; boneRule < BoneRule.BoneRuleEnd; ++boneRule) {
switch (boneRule) {
case BoneRule.RecommendedUnityVersion:
// iterate over all avatar rules in order and add any rules that fail
// to the failed avatar rules map with appropriate error or warning text
for (AvatarRule avatarRule = 0; avatarRule < AvatarRule.AvatarRuleEnd; ++avatarRule) {
switch (avatarRule) {
case AvatarRule.RecommendedUnityVersion:
if (Array.IndexOf(RECOMMENDED_UNITY_VERSIONS, Application.unityVersion) == -1) {
failedBoneRules.Add(boneRule, "The current version of Unity is not one of the recommended Unity " +
"versions. If you are using a version of Unity later than 2018.2.12f1, " +
"it is recommended to apply Enforce T-Pose under the Pose dropdown " +
"in Humanoid configuration.");
failedAvatarRules.Add(avatarRule, "The current version of Unity is not one of the recommended Unity " +
"versions. If you are using a version of Unity later than 2018.2.12f1, " +
"it is recommended to apply Enforce T-Pose under the Pose dropdown " +
"in Humanoid configuration.");
}
break;
case BoneRule.SingleRoot:
// bone rule fails if the root bone node has more than one child bone
case AvatarRule.SingleRoot:
// avatar rule fails if the root bone node has more than one child bone
if (userBoneTree.children.Count > 1) {
failedBoneRules.Add(boneRule, "There is more than one bone at the top level of the selected avatar's " +
"bone hierarchy. Please ensure all bones for Humanoid mappings are " +
"under the same bone hierarchy.");
failedAvatarRules.Add(avatarRule, "There is more than one bone at the top level of the selected avatar's " +
"bone hierarchy. Please ensure all bones for Humanoid mappings are " +
"under the same bone hierarchy.");
}
break;
case BoneRule.NoDuplicateMapping:
// bone rule fails if any user bone is mapped to more than one Humanoid bone
case AvatarRule.NoDuplicateMapping:
// avatar rule fails if any user bone is mapped to more than one Humanoid bone
foreach (var userBoneInfo in userBoneInfos) {
string boneName = userBoneInfo.Key;
int mappingCount = userBoneInfo.Value.mappingCount;
if (mappingCount > 1) {
string text = "The " + boneName + " bone is mapped to more than one bone in Humanoid.";
if (failedBoneRules.ContainsKey(boneRule)) {
failedBoneRules[boneRule] += "\n" + text;
if (failedAvatarRules.ContainsKey(avatarRule)) {
failedAvatarRules[avatarRule] += "\n" + text;
} else {
failedBoneRules.Add(boneRule, text);
failedAvatarRules.Add(avatarRule, text);
}
}
}
break;
case BoneRule.NoAsymmetricalLegMapping:
CheckAsymmetricalMappingRule(boneRule, LEG_MAPPING_SUFFIXES, "leg");
case AvatarRule.NoAsymmetricalLegMapping:
CheckAsymmetricalMappingRule(avatarRule, LEG_MAPPING_SUFFIXES, "leg");
break;
case BoneRule.NoAsymmetricalArmMapping:
CheckAsymmetricalMappingRule(boneRule, ARM_MAPPING_SUFFIXES, "arm");
case AvatarRule.NoAsymmetricalArmMapping:
CheckAsymmetricalMappingRule(avatarRule, ARM_MAPPING_SUFFIXES, "arm");
break;
case BoneRule.NoAsymmetricalHandMapping:
CheckAsymmetricalMappingRule(boneRule, HAND_MAPPING_SUFFIXES, "hand");
case AvatarRule.NoAsymmetricalHandMapping:
CheckAsymmetricalMappingRule(avatarRule, HAND_MAPPING_SUFFIXES, "hand");
break;
case BoneRule.HipsMapped:
hipsUserBone = CheckHumanBoneMappingRule(boneRule, "Hips");
case AvatarRule.HipsMapped:
hipsUserBone = CheckHumanBoneMappingRule(avatarRule, "Hips");
break;
case BoneRule.SpineMapped:
spineUserBone = CheckHumanBoneMappingRule(boneRule, "Spine");
case AvatarRule.SpineMapped:
spineUserBone = CheckHumanBoneMappingRule(avatarRule, "Spine");
break;
case BoneRule.SpineDescendantOfHips:
CheckUserBoneDescendantOfHumanRule(boneRule, spineUserBone, "Hips");
case AvatarRule.SpineDescendantOfHips:
CheckUserBoneDescendantOfHumanRule(avatarRule, spineUserBone, "Hips");
break;
case BoneRule.ChestMapped:
case AvatarRule.ChestMapped:
if (!humanoidToUserBoneMappings.TryGetValue("Chest", out chestUserBone)) {
// check to see if there is a child of Spine that we can suggest to be mapped to Chest
string spineChild = "";
@ -755,54 +868,54 @@ class AvatarExporter : MonoBehaviour {
spineChild = spineTreeNode.children[0].boneName;
}
}
failedBoneRules.Add(boneRule, "There is no Chest bone mapped in Humanoid for the selected avatar.");
failedAvatarRules.Add(avatarRule, "There is no Chest bone mapped in Humanoid for the selected avatar.");
// if the only found child of Spine is not yet mapped then add it as a suggestion for Chest mapping
if (!string.IsNullOrEmpty(spineChild) && !userBoneInfos[spineChild].HasHumanMapping()) {
failedBoneRules[boneRule] += " It is suggested that you map bone " + spineChild +
" to Chest in Humanoid.";
failedAvatarRules[avatarRule] += " It is suggested that you map bone " + spineChild +
" to Chest in Humanoid.";
}
}
break;
case BoneRule.ChestDescendantOfSpine:
CheckUserBoneDescendantOfHumanRule(boneRule, chestUserBone, "Spine");
case AvatarRule.ChestDescendantOfSpine:
CheckUserBoneDescendantOfHumanRule(avatarRule, chestUserBone, "Spine");
break;
case BoneRule.NeckMapped:
CheckHumanBoneMappingRule(boneRule, "Neck");
case AvatarRule.NeckMapped:
CheckHumanBoneMappingRule(avatarRule, "Neck");
break;
case BoneRule.HeadMapped:
headUserBone = CheckHumanBoneMappingRule(boneRule, "Head");
case AvatarRule.HeadMapped:
headUserBone = CheckHumanBoneMappingRule(avatarRule, "Head");
break;
case BoneRule.HeadDescendantOfChest:
CheckUserBoneDescendantOfHumanRule(boneRule, headUserBone, "Chest");
case AvatarRule.HeadDescendantOfChest:
CheckUserBoneDescendantOfHumanRule(avatarRule, headUserBone, "Chest");
break;
case BoneRule.EyesMapped:
case AvatarRule.EyesMapped:
bool leftEyeMapped = humanoidToUserBoneMappings.ContainsKey("LeftEye");
bool rightEyeMapped = humanoidToUserBoneMappings.ContainsKey("RightEye");
if (!leftEyeMapped || !rightEyeMapped) {
if (leftEyeMapped && !rightEyeMapped) {
failedBoneRules.Add(boneRule, "There is no RightEye bone mapped in Humanoid " +
"for the selected avatar.");
failedAvatarRules.Add(avatarRule, "There is no RightEye bone mapped in Humanoid " +
"for the selected avatar.");
} else if (!leftEyeMapped && rightEyeMapped) {
failedBoneRules.Add(boneRule, "There is no LeftEye bone mapped in Humanoid " +
"for the selected avatar.");
failedAvatarRules.Add(avatarRule, "There is no LeftEye bone mapped in Humanoid " +
"for the selected avatar.");
} else {
failedBoneRules.Add(boneRule, "There is no LeftEye or RightEye bone mapped in Humanoid " +
"for the selected avatar.");
failedAvatarRules.Add(avatarRule, "There is no LeftEye or RightEye bone mapped in Humanoid " +
"for the selected avatar.");
}
}
break;
case BoneRule.HipsNotOnGround:
case AvatarRule.HipsNotOnGround:
// ensure the absolute Y position for the bone mapped to Hips (if its mapped) is at least HIPS_GROUND_MIN_Y
if (!string.IsNullOrEmpty(hipsUserBone)) {
UserBoneInformation hipsBoneInfo = userBoneInfos[hipsUserBone];
hipsPosition = hipsBoneInfo.position;
if (hipsPosition.y < HIPS_GROUND_MIN_Y) {
failedBoneRules.Add(boneRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone +
") should not be at ground level.");
failedAvatarRules.Add(avatarRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone +
") should not be at ground level.");
}
}
break;
case BoneRule.HipsSpineChestNotCoincident:
case AvatarRule.HipsSpineChestNotCoincident:
// ensure the bones mapped to Hips, Spine, and Chest are all not in the same position,
// check Hips to Spine and Spine to Chest lengths are within HIPS_SPINE_CHEST_MIN_SEPARATION
if (!string.IsNullOrEmpty(spineUserBone) && !string.IsNullOrEmpty(chestUserBone) &&
@ -813,34 +926,34 @@ class AvatarExporter : MonoBehaviour {
Vector3 spineToChest = spineBoneInfo.position - chestBoneInfo.position;
if (hipsToSpine.magnitude < HIPS_SPINE_CHEST_MIN_SEPARATION &&
spineToChest.magnitude < HIPS_SPINE_CHEST_MIN_SEPARATION) {
failedBoneRules.Add(boneRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone +
"), the bone mapped to Spine in Humanoid (" + spineUserBone +
"), and the bone mapped to Chest in Humanoid (" + chestUserBone +
") should not be coincidental.");
failedAvatarRules.Add(avatarRule, "The bone mapped to Hips in Humanoid (" + hipsUserBone +
"), the bone mapped to Spine in Humanoid (" + spineUserBone +
"), and the bone mapped to Chest in Humanoid (" + chestUserBone +
") should not be coincidental.");
}
}
break;
case BoneRule.TotalBoneCountUnderLimit:
case AvatarRule.TotalBoneCountUnderLimit:
int userBoneCount = userBoneInfos.Count;
if (userBoneCount > MAXIMUM_USER_BONE_COUNT) {
failedBoneRules.Add(boneRule, "The total number of bones in the avatar (" + userBoneCount +
") exceeds the maximum bone limit (" + MAXIMUM_USER_BONE_COUNT + ").");
failedAvatarRules.Add(avatarRule, "The total number of bones in the avatar (" + userBoneCount +
") exceeds the maximum bone limit (" + MAXIMUM_USER_BONE_COUNT + ").");
}
break;
}
}
}
static string CheckHumanBoneMappingRule(BoneRule boneRule, string humanBoneName) {
static string CheckHumanBoneMappingRule(AvatarRule avatarRule, string humanBoneName) {
string userBoneName = "";
// bone rule fails if bone is not mapped in Humanoid
// avatar rule fails if bone is not mapped in Humanoid
if (!humanoidToUserBoneMappings.TryGetValue(humanBoneName, out userBoneName)) {
failedBoneRules.Add(boneRule, "There is no " + humanBoneName + " bone mapped in Humanoid for the selected avatar.");
failedAvatarRules.Add(avatarRule, "There is no " + humanBoneName + " bone mapped in Humanoid for the selected avatar.");
}
return userBoneName;
}
static void CheckUserBoneDescendantOfHumanRule(BoneRule boneRule, string userBoneName, string descendantOfHumanName) {
static void CheckUserBoneDescendantOfHumanRule(AvatarRule avatarRule, string userBoneName, string descendantOfHumanName) {
if (string.IsNullOrEmpty(userBoneName)) {
return;
}
@ -867,13 +980,13 @@ class AvatarExporter : MonoBehaviour {
}
}
// bone rule fails if no ancestor of given user bone matched the descendant of name (no early return)
failedBoneRules.Add(boneRule, "The bone mapped to " + userBoneInfo.humanName + " in Humanoid (" + userBoneName +
") is not a child of the bone mapped to " + descendantOfHumanName + " in Humanoid (" +
descendantOfUserBoneName + ").");
// avatar rule fails if no ancestor of given user bone matched the descendant of name (no early return)
failedAvatarRules.Add(avatarRule, "The bone mapped to " + userBoneInfo.humanName + " in Humanoid (" + userBoneName +
") is not a child of the bone mapped to " + descendantOfHumanName + " in Humanoid (" +
descendantOfUserBoneName + ").");
}
static void CheckAsymmetricalMappingRule(BoneRule boneRule, string[] mappingSuffixes, string appendage) {
static void CheckAsymmetricalMappingRule(AvatarRule avatarRule, string[] mappingSuffixes, string appendage) {
int leftCount = 0;
int rightCount = 0;
// add Left/Right to each mapping suffix to make Humanoid mapping names,
@ -888,23 +1001,23 @@ class AvatarExporter : MonoBehaviour {
++rightCount;
}
}
// bone rule fails if number of left appendage mappings doesn't match number of right appendage mappings
// avatar rule fails if number of left appendage mappings doesn't match number of right appendage mappings
if (leftCount != rightCount) {
failedBoneRules.Add(boneRule, "The number of bones mapped in Humanoid for the left " + appendage + " (" +
leftCount + ") does not match the number of bones mapped in Humanoid for the right " +
appendage + " (" + rightCount + ").");
failedAvatarRules.Add(avatarRule, "The number of bones mapped in Humanoid for the left " + appendage + " (" +
leftCount + ") does not match the number of bones mapped in Humanoid for the right " +
appendage + " (" + rightCount + ").");
}
}
static string GetTextureDirectory(string basePath) {
string textureDirectory = Path.GetDirectoryName(basePath) + "\\textures";
string textureDirectory = Path.GetDirectoryName(basePath) + "\\" + TEXTURES_DIRECTORY;
textureDirectory = textureDirectory.Replace("\\\\", "\\");
return textureDirectory;
}
static string SetTextureDependencies() {
string textureWarnings = "";
dependencyTextures.Clear();
textureDependencies.Clear();
// build the list of all local asset paths for textures that Unity considers dependencies of the model
// for any textures that have duplicate names, return a string of duplicate name warnings
@ -913,11 +1026,11 @@ class AvatarExporter : MonoBehaviour {
UnityEngine.Object textureObject = AssetDatabase.LoadAssetAtPath(dependencyPath, typeof(Texture2D));
if (textureObject != null) {
string textureName = Path.GetFileName(dependencyPath);
if (dependencyTextures.ContainsKey(textureName)) {
if (textureDependencies.ContainsKey(textureName)) {
textureWarnings += "There is more than one texture with the name " + textureName +
" referenced in the selected avatar.\n\n";
} else {
dependencyTextures.Add(textureName, dependencyPath);
textureDependencies.Add(textureName, dependencyPath);
}
}
}
@ -927,7 +1040,7 @@ class AvatarExporter : MonoBehaviour {
static bool CopyExternalTextures(string texturesDirectory) {
// copy the found dependency textures from the local asset folder to the textures folder in the target export project
foreach (var texture in dependencyTextures) {
foreach (var texture in textureDependencies) {
string targetPath = texturesDirectory + "\\" + texture.Key;
try {
File.Copy(texture.Value, targetPath, true);
@ -939,6 +1052,88 @@ class AvatarExporter : MonoBehaviour {
}
return true;
}
static void StoreMaterialData(Material[] materials) {
// store each material's info in the materialDatas list to be written out later to the FST if it is a supported shader
foreach (Material material in materials) {
string materialName = material.name;
string shaderName = material.shader.name;
// don't store any material data for unsupported shader types
if (Array.IndexOf(SUPPORTED_SHADERS, shaderName) == -1) {
if (!materialUnsupportedShader.ContainsKey(materialName)) {
materialUnsupportedShader.Add(materialName, shaderName);
}
continue;
}
MaterialData materialData = new MaterialData();
materialData.albedo = material.GetColor("_Color");
materialData.albedoMap = GetMaterialTexture(material, "_MainTex");
materialData.roughness = material.GetFloat("_Glossiness");
materialData.roughnessMap = GetMaterialTexture(material, "_SpecGlossMap");
materialData.normalMap = GetMaterialTexture(material, "_BumpMap");
materialData.occlusionMap = GetMaterialTexture(material, "_OcclusionMap");
materialData.emissive = material.GetColor("_EmissionColor");
materialData.emissiveMap = GetMaterialTexture(material, "_EmissionMap");
// for specular setups we will treat the metallic value as the average of the specular RGB intensities
if (shaderName == STANDARD_SPECULAR_SHADER) {
Color specular = material.GetColor("_SpecColor");
materialData.metallic = (specular.r + specular.g + specular.b) / 3.0f;
} else {
materialData.metallic = material.GetFloat("_Metallic");
materialData.metallicMap = GetMaterialTexture(material, "_MetallicGlossMap");
}
// for non-roughness Standard shaders give a warning that is not the recommended Standard shader,
// and invert smoothness for roughness
if (shaderName == STANDARD_SHADER || shaderName == STANDARD_SPECULAR_SHADER) {
if (!materialAlternateStandardShader.Contains(materialName)) {
materialAlternateStandardShader.Add(materialName);
}
materialData.roughness = 1.0f - materialData.roughness;
}
// remap the material name from the Unity material name to the fbx material name that it overrides
if (materialMappings.ContainsKey(materialName)) {
materialName = materialMappings[materialName];
}
if (!materialDatas.ContainsKey(materialName)) {
materialDatas.Add(materialName, materialData);
}
}
}
static string GetMaterialTexture(Material material, string textureProperty) {
// ensure the texture property name exists in this material and return its texture directory path if so
string[] textureNames = material.GetTexturePropertyNames();
if (Array.IndexOf(textureNames, textureProperty) >= 0) {
Texture texture = material.GetTexture(textureProperty);
if (texture) {
foreach (var textureDependency in textureDependencies) {
string textureFile = textureDependency.Key;
if (Path.GetFileNameWithoutExtension(textureFile) == texture.name) {
return TEXTURES_DIRECTORY + "/" + textureFile;
}
}
}
}
return "";
}
static void SetMaterialMappings() {
materialMappings.Clear();
// store the mappings from fbx material name to the Unity material name overriding it using external fbx mapping
var objectMap = modelImporter.GetExternalObjectMap();
foreach (var mapping in objectMap) {
var material = mapping.Value as UnityEngine.Material;
if (material != null) {
materialMappings.Add(material.name, mapping.Key.name);
}
}
}
}
class ExportProjectWindow : EditorWindow {

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 00403fdc52187214c8418bc0a7f387e2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,7 +1,6 @@
High Fidelity, Inc.
Avatar Exporter
Version 0.2
Version 0.3.1
Note: It is recommended to use Unity versions between 2017.4.17f1 and 2018.2.12f1 for this Avatar Exporter.

View file

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 30b2b6221fd08234eb07c4d6d525d32e
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: