Added flow to the repository.

This commit is contained in:
armored-dragon 2024-08-27 23:17:50 -05:00
parent 242bd78b46
commit 30ff8c04b2
No known key found for this signature in database
GPG key ID: C7207ACC3382AD8B
6 changed files with 1010 additions and 0 deletions

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
viewBox="0 0 50 50"
style="enable-background:new 0 0 50 50;"
xml:space="preserve"
id="svg2"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="bubble-a.svg"><metadata
id="metadata36"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs34" /><sodipodi:namedview
pagecolor="#ff4900"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview32"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="11.866642"
inkscape:cy="25.215464"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" /><style
type="text/css"
id="style4">
.st0{fill:#FFFFFF;}
</style><path
d="m 23.320771,4.5599089 c -4.698286,0.5905206 -7.707907,4.8163347 -6.771959,9.5081161 0.332972,1.668875 0.726422,2.070767 2.047378,2.090834 2.235869,0.03391 4.394653,1.180349 5.446851,2.892402 0.723516,1.177028 1.103542,1.28968 2.63264,0.77998 5.199405,-1.733089 7.069087,-8.118932 3.626298,-12.3854339 C 28.638363,5.3843128 25.869406,4.2396687 23.320771,4.5599089 m -1.447862,2.6947782 c 0.591212,0.17562 1.033653,0.777904 1.035175,1.4092505 0.003,1.3295364 -1.563004,1.9826104 -2.502136,1.0434792 -1.09676,-1.0967603 -0.02145,-2.8947553 1.466961,-2.4527297 M 18.773194,17.695984 c -0.643248,0.177972 -0.329374,-0.340999 -4.791424,7.926982 -1.172599,2.1729 -1.173983,2.356132 -0.02007,2.850331 0.805168,0.344736 1.368978,0.646708 2.028142,1.086243 1.503634,1.002376 1.408974,1.064376 3.073143,-2.016655 0.483128,-0.894569 1.462532,-2.706542 2.176222,-4.026391 1.705548,-3.153964 1.726584,-3.211259 1.408143,-3.850355 -0.544436,-1.09247 -2.835523,-2.257596 -3.874159,-1.970155 m 12.19556,1.254112 c -0.117219,0.0537 -0.441195,0.284258 -0.719918,0.512468 -0.650306,0.532672 -1.136756,0.85997 -1.793289,1.206228 -1.45409,0.766971 -1.454505,0.746905 0.07113,3.460919 0.469981,0.836029 1.352233,2.407891 1.960606,3.493165 2.246941,4.007846 2.19878,3.93173 2.619355,4.135305 0.954077,0.461954 3.885922,-1.044586 4.211283,-2.163766 0.170499,-0.586231 0.388329,-0.134241 -2.773247,-5.753667 -3.036469,-5.397307 -2.89434,-5.202727 -3.575923,-4.890652 M 9.47668,29.440522 c -6.2139603,0.959475 -8.82528785,8.593204 -4.5021839,13.161124 2.9044428,3.068992 7.5029479,3.29983 10.8153719,0.542914 1.333411,-1.109769 1.546536,-1.710254 0.990475,-2.790823 -0.850422,-1.652821 -0.853052,-4.600581 -0.0057,-6.270701 0.533227,-1.051091 0.457249,-1.367179 -0.57848,-2.405538 -1.75191,-1.756339 -4.312171,-2.608559 -6.719508,-2.236976 m 30.158349,0.103656 c -0.322316,0.105871 -0.493508,0.265991 -1.02964,0.962797 -1.288157,1.673857 -3.057228,2.647032 -5.321606,2.927416 -1.295907,0.160396 -1.57629,0.399262 -1.939155,1.651575 -1.673442,5.774426 3.633494,11.219201 9.490263,9.737018 5.357173,-1.355693 7.678153,-7.871902 4.372787,-12.276104 -1.4015,-1.86733 -4.290582,-3.423968 -5.572649,-3.002702 M 8.1615363,32.931611 c 0.7665559,0.338231 1.1003585,1.242211 0.7347256,1.98953 -0.4463157,0.912283 -1.6149017,1.120979 -2.3439532,0.41836 -1.1856083,-1.142429 0.1040711,-3.072174 1.6092276,-2.40789 m 10.6627247,1.707624 c -0.951863,0.142683 -1.204983,0.783163 -1.14672,2.901952 0.03847,1.401362 0.184616,1.848924 0.691962,2.120034 l 0.226687,0.121094 h 5.226392 c 5.130485,0 5.229713,-0.0021 5.407409,-0.106701 0.370061,-0.217968 0.408396,-0.326883 0.382378,-1.084858 -0.03709,-1.079323 -0.03211,-2.013334 0.01439,-2.701698 0.05328,-0.787453 -0.0018,-0.938439 -0.417807,-1.146582 l -0.266682,-0.133272 -4.906428,-0.0079 c -2.698515,-0.0043 -5.043714,0.01273 -5.211584,0.03792 m 16.640726,0.779288 c 0.677154,0.24108 1.100912,1.175921 0.846131,1.867053 -0.466382,1.264907 -2.350042,1.288296 -2.77726,0.03432 -0.425003,-1.247332 0.688503,-2.343677 1.931129,-1.901375"
id="path0"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1" /><style
id="style4-0"
type="text/css">
.st0{fill:#FFFFFF;}
</style></svg>

After

(image error) Size: 4.8 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
viewBox="0 0 50 50"
style="enable-background:new 0 0 50 50;"
xml:space="preserve"
id="svg2"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="bubble-i.svg"><metadata
id="metadata36"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs34" /><sodipodi:namedview
pagecolor="#ff4900"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview32"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="11.866642"
inkscape:cy="25.215464"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" /><style
type="text/css"
id="style4">
.st0{fill:#FFFFFF;}
</style>
<path
d="m 23.320771,4.5599089 c -4.698286,0.5905206 -7.707907,4.8163347 -6.771959,9.5081161 0.332972,1.668875 0.726422,2.070767 2.047378,2.090834 2.235869,0.03391 4.394653,1.180349 5.446851,2.892402 0.723516,1.177028 1.103542,1.28968 2.63264,0.77998 5.199405,-1.733089 7.069087,-8.118932 3.626298,-12.3854339 C 28.638363,5.3843128 25.869406,4.2396687 23.320771,4.5599089 m -1.447862,2.6947782 c 0.591212,0.17562 1.033653,0.777904 1.035175,1.4092505 0.003,1.3295364 -1.563004,1.9826104 -2.502136,1.0434792 -1.09676,-1.0967603 -0.02145,-2.8947553 1.466961,-2.4527297 M 18.773194,17.695984 c -0.643248,0.177972 -0.329374,-0.340999 -4.791424,7.926982 -1.172599,2.1729 -1.173983,2.356132 -0.02007,2.850331 0.805168,0.344736 1.368978,0.646708 2.028142,1.086243 1.503634,1.002376 1.408974,1.064376 3.073143,-2.016655 0.483128,-0.894569 1.462532,-2.706542 2.176222,-4.026391 1.705548,-3.153964 1.726584,-3.211259 1.408143,-3.850355 -0.544436,-1.09247 -2.835523,-2.257596 -3.874159,-1.970155 m 12.19556,1.254112 c -0.117219,0.0537 -0.441195,0.284258 -0.719918,0.512468 -0.650306,0.532672 -1.136756,0.85997 -1.793289,1.206228 -1.45409,0.766971 -1.454505,0.746905 0.07113,3.460919 0.469981,0.836029 1.352233,2.407891 1.960606,3.493165 2.246941,4.007846 2.19878,3.93173 2.619355,4.135305 0.954077,0.461954 3.885922,-1.044586 4.211283,-2.163766 0.170499,-0.586231 0.388329,-0.134241 -2.773247,-5.753667 -3.036469,-5.397307 -2.89434,-5.202727 -3.575923,-4.890652 M 9.47668,29.440522 c -6.2139603,0.959475 -8.82528785,8.593204 -4.5021839,13.161124 2.9044428,3.068992 7.5029479,3.29983 10.8153719,0.542914 1.333411,-1.109769 1.546536,-1.710254 0.990475,-2.790823 -0.850422,-1.652821 -0.853052,-4.600581 -0.0057,-6.270701 0.533227,-1.051091 0.457249,-1.367179 -0.57848,-2.405538 -1.75191,-1.756339 -4.312171,-2.608559 -6.719508,-2.236976 m 30.158349,0.103656 c -0.322316,0.105871 -0.493508,0.265991 -1.02964,0.962797 -1.288157,1.673857 -3.057228,2.647032 -5.321606,2.927416 -1.295907,0.160396 -1.57629,0.399262 -1.939155,1.651575 -1.673442,5.774426 3.633494,11.219201 9.490263,9.737018 5.357173,-1.355693 7.678153,-7.871902 4.372787,-12.276104 -1.4015,-1.86733 -4.290582,-3.423968 -5.572649,-3.002702 M 8.1615363,32.931611 c 0.7665559,0.338231 1.1003585,1.242211 0.7347256,1.98953 -0.4463157,0.912283 -1.6149017,1.120979 -2.3439532,0.41836 -1.1856083,-1.142429 0.1040711,-3.072174 1.6092276,-2.40789 m 10.6627247,1.707624 c -0.951863,0.142683 -1.204983,0.783163 -1.14672,2.901952 0.03847,1.401362 0.184616,1.848924 0.691962,2.120034 l 0.226687,0.121094 h 5.226392 c 5.130485,0 5.229713,-0.0021 5.407409,-0.106701 0.370061,-0.217968 0.408396,-0.326883 0.382378,-1.084858 -0.03709,-1.079323 -0.03211,-2.013334 0.01439,-2.701698 0.05328,-0.787453 -0.0018,-0.938439 -0.417807,-1.146582 l -0.266682,-0.133272 -4.906428,-0.0079 c -2.698515,-0.0043 -5.043714,0.01273 -5.211584,0.03792 m 16.640726,0.779288 c 0.677154,0.24108 1.100912,1.175921 0.846131,1.867053 -0.466382,1.264907 -2.350042,1.288296 -2.77726,0.03432 -0.425003,-1.247332 0.688503,-2.343677 1.931129,-1.901375"
id="path0"
inkscape:connector-curvature="0"
style="fill:#FFFFFF;fill-opacity:1;stroke:none" />
<style
id="style4-0"
type="text/css">
.st0{fill:#FFFFFF;}
</style>
</svg>

After

(image error) Size: 4.8 KiB

View file

@ -0,0 +1,393 @@
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script>
//
// Created by Luis Cuenca on 1/31/18
// Copyright 2018 High Fidelity, Inc.
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* jslint bitwise: true */
/* global $, EventBridge
*/
$(function () {
var MSG_DOCUMENT_LOADED = 0;
var MSG_JOINT_INPUT_DATA = 1;
var MSG_COLLISION_DATA = 2;
var MSG_COLLISION_INPUT_DATA = 3;
var MSG_DISPLAY_DATA = 4;
var MSG_CREATE = 5;
var MSG_UPDATE_DATA = 6;
var KIND_JOINT = "joint";
var KIND_COLLISION = "collision";
var KIND_DISPLAY = "display";
var OUTPUT_MODES = {"fst" : 0};
var groupData, collisionData;
function createInput(kind, group, name, type, config) {
var input = $("<input>").attr("type", type).attr("data-name", name).attr("data-group", group).attr("data-kind", kind);
var inputId = kind + "-" + group + "-" + type + "-" + name;
input.attr("id", inputId).attr("name", inputId);
if (type === "range") {
input.attr("step", config.step).attr("value", config.value).attr("min", config.min).attr("max", config.max);
} else if (type === "checkbox" && config.checked) {
input.attr("checked", "checked");
}
return input;
}
function createElement(kind, group, name, type, config) {
var element = $("<div>").addClass("unit-config half");
var input = createInput(kind, group, name, type, config);
var label = $("<label>").text(name).attr("for", input.attr("id"));
element.append(label).append(input);
return element;
}
function createGroupContainer(name, type) {
var groupContainer = $("<div>").addClass("ui-corner-all custom-corners");
var bartype = type ? "ui-bar-" + type : "ui-bar-b";
var headContainer = $("<div>").addClass("ui-bar " + bartype);
var header = $("<h3>").addClass("header-text").text(name);
var contentContainer = $("<div>").addClass("group-content ui-body ui-body-a");
headContainer.append(header);
groupContainer.append(headContainer).append(contentContainer);
return groupContainer;
}
function createGroup(kind, name, elements, type) {
var group = createGroupContainer(name, type);
var content = group.find(".group-content");
for (var i = 0; i < elements.length; i++){
if (elements[i].type) {
content.append(createElement(kind, name, elements[i].name, elements[i].type, elements[i].config));
} else {
content.append(elements[i]);
}
}
return group;
}
function getGroupJSON(mode) {
var result = "";
var groupDataClone = JSON.parse(JSON.stringify(groupData));
Object.keys(groupData).forEach(function(key){
delete groupDataClone[key].jointIndices;
});
switch (mode) {
case OUTPUT_MODES.flow:
result = "CUSTOM_FLOW_DATA = " + JSON.stringify(groupDataClone) + ";\n";
break;
case OUTPUT_MODES.fst:
Object.keys(groupDataClone).forEach(function(group) {
var fstline = {};
fstline[group] = groupDataClone[group];
result += "flowPhysicsData = " + JSON.stringify(fstline) + "\n";
});
break;
default:
break;
}
return result;
}
function getCollisionJSON(mode) {
var result = "";
var collisionDataClone = JSON.parse(JSON.stringify(collisionData));
Object.keys(collisionData).forEach(function(key){
collisionDataClone[key]["type"] = "sphere";
delete collisionDataClone[key].jointIndex;
});
switch (mode) {
case OUTPUT_MODES.flow:
result = "CUSTOM_COLLISION_DATA = " + JSON.stringify(collisionDataClone) + ";\n";
break;
case OUTPUT_MODES.fst:
Object.keys(collisionDataClone).forEach(function(jointName) {
if (jointName != "LeftHandMiddle1" && jointName != "LeftHandMiddle3" && jointName != "LeftHandThumb3"
&& jointName != "RightHandMiddle1" && jointName != "RightHandMiddle3" && jointName != "RightHandThumb3") {
var fstline = {};
fstline[jointName] = collisionDataClone[jointName];
result += "flowCollisionsData = " + JSON.stringify(fstline) + "\n";
}
});
break;
default:
break;
}
return result;
}
function createDump(label, id, addon) {
var group = createGroupContainer(label);
if (addon) {
var bar = group.find(".ui-bar");
var barAddon = $("<span>").addClass("bar-addon").addClass("right").text(addon);
bar.append(barAddon);
}
var content = group.find(".group-content");
var dumpBox = $("<textarea>").attr("wrap","off").attr("rows", 11).attr("id", id);
content.append(dumpBox);
return group;
}
function updateDump() {
if (groupData) {
var modes = Object.keys(OUTPUT_MODES);
for (i = 0; i < modes.length; i++) {
var mode = OUTPUT_MODES[modes[i]];
var isCollisionEnabled = $("#display-display-checkbox-collisions").prop("checked");
var collisionCount = Object.keys(collisionData).length;
var groupCount = Object.keys(groupData).length;
var hasCollisions = isCollisionEnabled && collisionCount > 0;
var rows = mode === OUTPUT_MODES.flow ? 3 : collisionCount + groupCount + 1;
$("#dump-box-" + modes[i]).addClass("dump-box").attr("rows", rows).val(getGroupJSON(mode) + getCollisionJSON(mode));
}
}
}
function createJointDropdown(joints, parentElement) {
var container = $("<fieldset data-role='controlgroup' data-type='horizontal'>");
var select = $("<select>").attr("id", "joint-select");
for (var i = 0; i < joints.length; i++) {
var option = $("<option>").attr("value", joints[i]).text(joints[i]);
select.append(option);
}
var button = $("<button>").addClass("add-joint").text("Add").click(function(){
var joint = $("#joint-select").val();
EventBridge.emitWebEvent(JSON.stringify({type:MSG_COLLISION_DATA, name: "add", value: joint}));
});
container.append(select);
container.append(button);
var group = createGroup(KIND_COLLISION, "Manage Collisions", [container]);
parentElement.append(group);
}
function createCollisionGroup(name, collisionSettings) {
var controls = [
{name: "radius", type: "range", config: {"step": 0.01, "value": collisionSettings.radius, "min":0.01, "max":0.5}},
{name: "offset", type: "range", config: {"step": 0.05, "value": collisionSettings.offset.y, "min":-0.3, "max":0.3}}
];
var groupElement = createGroup(KIND_COLLISION, name, controls, "a");
var headbar = groupElement.find(".ui-bar");
headbar.data("joint", name).addClass("ui-nodisc-icon ui-alt-icon");
var deleteBtn = $("<a>").addClass("ui-btn ui-corner-all ui-shadow ui-btn-inline ui-icon-delete ui-btn-icon-notext thin right");
deleteBtn.click(function(){
var parent = $(this).parent();
var joint = parent.data("joint");
parent.parent().remove();
EventBridge.emitWebEvent(JSON.stringify({type:MSG_COLLISION_DATA, name: "remove", value: joint}));
delete collisionData[joint];
});
headbar.append(deleteBtn);
return groupElement;
}
function configureInputs(selector) {
$(selector).find("input").change(function() {
var kind = $(this).data("kind");
var group = $(this).data("group");
var name = $(this).data("name");
var value = this.value;
var type;
switch(kind) {
case KIND_COLLISION:
type = MSG_COLLISION_INPUT_DATA;
if (name === "offset") {
collisionData[group].offset.y = eval(value);
} else {
collisionData[group][name] = eval(value);
}
break;
case KIND_JOINT: {
type = MSG_JOINT_INPUT_DATA;
if (name === "active") {
value = $(this).prop("checked");
groupData[group][name] = eval(value);
} else {
groupData[group][name] = eval(value);
}
break;
}
case KIND_DISPLAY: {
type = MSG_DISPLAY_DATA;
break;
}
}
EventBridge.emitWebEvent(JSON.stringify({type: type, group: group, name: name, value: value}));
});
}
EventBridge.scriptEventReceived.connect(function (msg) {
var message = JSON.parse(msg);
if (message.type === MSG_CREATE) {
$("#joints-panel").empty();
$("#collisions-panel").empty();
$("#display-panel").empty();
groupData = message.data.group;
var filterKeys = Object.keys(groupData);
var controls;
for (var i = 0; i < filterKeys.length; i++) {
var parameters = groupData[filterKeys[i]];
controls = [
{name: "radius", type: "range", config: {"step": 0.01, "value": parameters.radius, "min":0.01, "max":0.1}},
{name: "stiffness", type: "range", config: {"step": 0.05, "value": parameters.stiffness, "min":0.0, "max":1.0}},
{name: "gravity", type: "range", config: {"step": 0.0001, "value": parameters.gravity, "min":-0.05, "max":0.05}},
{name: "damping", type: "range", config: {"step": 0.05, "value": parameters.damping, "min":0.0, "max":1.0}},
{name: "inertia", type: "range", config: {"step": 0.05, "value": parameters.inertia, "min":0.0, "max":1.0}},
{name: "delta", type: "range", config: {"step": 0.05, "value": parameters.delta, "min":0.0, "max":1.0}}
];
var groupElement = createGroup(KIND_JOINT, filterKeys[i], controls);
var enabler = createInput(KIND_JOINT, filterKeys[i], "active", "checkbox", {"checked": parameters.active}).addClass("joint-enabler");
$(groupElement).find(".ui-bar").append(enabler);
$("#joints-panel").append(groupElement);
}
controls = [
{name: "avatar", type: "checkbox", config: {"checked": message.data.display.avatar}},
{name: "collisions", type: "checkbox", config: {"checked": message.data.display.collisions}},
{name: "debug", type: "checkbox", config: {"checked": message.data.display.debug}},
{name: "solid", type: "checkbox", config: {"checked": message.data.display.solid}}
];
groupElement = createGroup(KIND_DISPLAY, "display", controls);
$("#display-panel").append(groupElement);
createJointDropdown(message.data.joints, $("#collisions-panel"));
collisionData = message.data.collisions;
var collisionKeys = Object.keys(collisionData);
for (i = 0; i < collisionKeys.length; i++) {
var jointName = collisionKeys[i];
var collisionGroup = createCollisionGroup(jointName, collisionData[jointName]);
$("#collisions-panel").append(collisionGroup);
}
$("#json-panel").append(createDump("FST", "dump-box-fst", "Add these lines to your .fst file"));
$("#joints-panel").trigger('create');
$("#collisions-panel").trigger('create');
$("#display-panel").trigger('create');
configureInputs("#joints-panel, #collisions-panel");
configureInputs("#display-panel");
$("#collisions-panel").hide();
$("#json-panel").hide();
} else if (message.type === MSG_COLLISION_DATA) {
collisionData[message.name] = message.data;
collisionGroup = createCollisionGroup(message.name, message.data);
$("#collisions-panel").append(collisionGroup);
collisionGroup.trigger('create');
configureInputs(collisionGroup);
}
});
$(".nav-text").click(function() {
var index = $(this).data("idx");
if (index === 0) {
$("#display-panel").show();
$("#collisions-panel").hide();
$("#joints-panel").show();
$("#json-panel").hide();
} else if (index === 1){
$("#display-panel").show();
$("#collisions-panel").show();
$("#joints-panel").hide();
$("#json-panel").hide();
} else {
$("#display-panel").hide();
$("#collisions-panel").hide();
$("#joints-panel").hide();
updateDump();
$("#json-panel").show();
}
});
EventBridge.emitWebEvent(JSON.stringify({type: MSG_DOCUMENT_LOADED}));
});
</script>
<head>
<meta charset="utf-8" />
<style>
.container {
margin:10px;
}
.unit-config.third{
width: 33%;
display: inline-block;
}
.unit-config.half{
width: 49.5%;
display: inline-block;
}
.nav-bar{
width: 440px;
}
.nav-text > a {
font-size: 20px !important;
}
.ui-controlgroup-controls {
width:100% !important;
}
.ui-select {
width:80% !important;
}
.right {
float: right;
}
.thin {
margin: 0px !important;
padding: 0px !important;
}
.joint-enabler {
margin-left: 390px !important;
margin-top: -25px !important;
}
.dump-box {
font-size: 14px;
font-family: monospace;
width:100%;
resize: none;
}
.bar-addon {
font-size: 12px;
}
</style>
<body>
<div id="nav-panel" style="margin:10px">
<div data-role="navbar" class="nav-bar">
<ul>
<li class="nav-text" data-idx=0 ><a href="#" class="ui-btn-active">Joints</a></li>
<li class="nav-text" data-idx=1 ><a href="#" >Collisions</a></li>
<li class="nav-text" data-idx=2 ><a href="#" >Output</a></li>
</ul>
</div><!-- /navbar -->
</div>
<div id="display-panel" class="container">
</div>
<div id="joints-panel" class="container">
</div>
<div id="collisions-panel" class="container">
</div>
<div id="json-panel" class="container">
</div>
</body>
</head>
</html>

View file

@ -0,0 +1,495 @@
//
// Created by Luis Cuenca on 3/8/19
// Copyright 2018 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* jslint bitwise: true */
/* global Script, MyAvatar, Tablet
*/
(function () {
// Adding some additional time before load fix an issue when updating the debugging overlays (local entities)
var MS_AFTER_LOADING = 500;
Script.setTimeout(function() {
Script.registerValue("FLOWAPP", true);
var TABLET_BUTTON_NAME = "FLOW";
var HTML_URL = Script.resolvePath("./flowAppCpp.html");
var SHOW_AVATAR = true;
var SHOW_DEBUG_SHAPES = false;
var SHOW_SOLID_SHAPES = false;
var POLYLINE_TEXTURE = Script.resolvePath("./polylineTexture.png");
var USE_COLLISIONS = false;
var IS_ACTIVE = false;
var MSG_DOCUMENT_LOADED = 0;
var MSG_JOINT_INPUT_DATA = 1;
var MSG_COLLISION_DATA = 2;
var MSG_COLLISION_INPUT_DATA = 3;
var MSG_DISPLAY_DATA = 4;
var MSG_CREATE = 5;
var avatarScale = MyAvatar.getSensorToWorldScale();
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var tabletButton = tablet.addButton({
text: TABLET_BUTTON_NAME,
icon: Script.resolvePath("./flow-i.svg"),
activeIcon: Script.resolvePath("./flow-a.svg")
});
var FlowDebug = function() {
var self = this;
this.debugLines = {};
this.debugSpheres = {};
this.showDebugShapes = false;
this.showSolidShapes = "lines"; // wireframe
this.setDebugLine = function(lineName, norms, startPosition, endPosition, shapeColor, width, forceRendering) {
var doRender = self.showDebugShapes || forceRendering;
if (!doRender) {
return;
}
var start = startPosition ? startPosition : {x: 0, y: 0, z: 0};
var end = endPosition ? endPosition : {x: 0, y: 1, z: 0};
var color = shapeColor ? shapeColor : { red: 0, green: 255, blue: 255 };
if (self.debugLines[lineName] !== undefined) {
Entities.editEntity(self.debugLines[lineName], {
color: color,
linePoints: [start, end],
strokeWidths: [width, width],
});
} else {
self.debugLines[lineName] = Entities.addEntity({
type: "PolyLine",
textures: POLYLINE_TEXTURE,
color: color,
normals: norms,
linePoints: [start, end],
visible: true,
strokeWidths: [width, width],
collisionless: true
}, "local");
}
};
this.setDebugSphere = function(sphereName, pos, diameter, shapeColor, forceRendering) {
var doRender = self.showDebugShapes || forceRendering;
if (!doRender) {
return;
}
var DEFAULT_SPHERE_DIAMETER = 0.02;
var scale = diameter ? diameter : DEFAULT_SPHERE_DIAMETER;
var color = shapeColor ? shapeColor : { red: 255, green: 0, blue: 255 };
if (self.debugSpheres[sphereName] !== undefined) {
Entities.editEntity(self.debugSpheres[sphereName], {
color: color,
position: pos,
dimensions: {x: scale, y: scale, z: scale},
primitiveMode: self.showSolidShapes,
});
} else {
self.debugSpheres[sphereName] = Entities.addEntity({
type: "Sphere",
color: color,
position: pos,
dimensions: {x: scale, y: scale, z: scale},
primitiveMode: self.showSolidShapes,
visible: true,
collisionless: true
}, "local");
}
};
this.deleteSphere = function(name) {
Entities.deleteEntity(self.debugSpheres[name]);
self.debugSpheres[name] = undefined;
};
this.deleteLine = function(name) {
Entities.deleteEntity(self.debugLines[name]);
self.debugLines[name] = undefined;
};
this.cleanup = function() {
for (var lineName in self.debugLines) {
if (lineName !== undefined) {
self.deleteLine(lineName);
}
}
for (var sphereName in self.debugSpheres) {
if (sphereName !== undefined) {
self.deleteSphere(sphereName);
}
}
self.debugLines = {};
self.debugSpheres = {};
};
this.setVisible = function(isVisible) {
self.showDebugShapes = isVisible;
for (var lineName in self.debugLines) {
if (lineName !== undefined) {
Entities.editEntity(self.debugLines[lineName], {
visible: isVisible
});
}
}
for (var sphereName in self.debugSpheres) {
if (sphereName !== undefined) {
Entities.editEntity(self.debugSpheres[sphereName], {
visible: isVisible
});
}
}
};
this.setSolid = function(isSolid) {
if(isSolid) {
self.showSolidShapes = "solid"
} else {
self.showSolidShapes = "lines"
}
for (var lineName in self.debugLines) {
if (lineName !== undefined) {
Entities.editEntity(self.debugLines[lineName], {
primitiveMode: self.showSolidShapes
});
}
}
for (var sphereName in self.debugSpheres) {
if (sphereName !== undefined) {
Entities.editEntity(self.debugSpheres[sphereName], {
primitiveMode: self.showSolidShapes
});
}
}
};
};
var flowData, initActive, initColliding, initDebugging;
updateFlowData(true);
var collisionDebug = new FlowDebug();
var jointDebug = new FlowDebug();
collisionDebug.setVisible(SHOW_DEBUG_SHAPES);
collisionDebug.setSolid(SHOW_SOLID_SHAPES);
MyAvatar.setEnableMeshVisible(SHOW_AVATAR);
jointDebug.setVisible(SHOW_DEBUG_SHAPES);
jointDebug.setSolid(SHOW_SOLID_SHAPES);
var shown = false;
function manageClick() {
if (shown) {
MyAvatar.useFlow(initActive, initColliding);
initDebugging = SHOW_DEBUG_SHAPES;
if (SHOW_DEBUG_SHAPES) {
toggleDebugShapes();
}
tablet.gotoHomeScreen();
} else {
updateFlowData();
tablet.gotoWebScreen(HTML_URL);
}
}
tabletButton.clicked.connect(manageClick);
function onScreenChanged(type, url) {
console.log("Screen changed");
if (type === "Web" && url === HTML_URL) {
tabletButton.editProperties({isActive: true});
if (!shown) {
// hook up to event bridge
tablet.webEventReceived.connect(onWebEventReceived);
}
shown = true;
} else {
tabletButton.editProperties({isActive: false});
if (shown) {
// disconnect from event bridge
tablet.webEventReceived.disconnect(onWebEventReceived);
}
shown = false;
}
}
var toggleAvatarVisible = function() {
SHOW_AVATAR = !SHOW_AVATAR;
MyAvatar.setEnableMeshVisible(SHOW_AVATAR);
};
var toggleDebugShapes = function() {
SHOW_DEBUG_SHAPES = !SHOW_DEBUG_SHAPES;
if (USE_COLLISIONS) {
collisionDebug.setVisible(SHOW_DEBUG_SHAPES);
}
jointDebug.setVisible(SHOW_DEBUG_SHAPES);
};
var toggleSolidShapes = function() {
SHOW_SOLID_SHAPES = !SHOW_SOLID_SHAPES;
collisionDebug.setSolid(SHOW_SOLID_SHAPES);
jointDebug.setSolid(SHOW_SOLID_SHAPES);
};
var toggleCollisions = function() {
USE_COLLISIONS = !USE_COLLISIONS;
if (USE_COLLISIONS && SHOW_DEBUG_SHAPES) {
collisionDebug.setVisible(true);
} else {
collisionDebug.setVisible(false);
}
MyAvatar.useFlow(IS_ACTIVE, USE_COLLISIONS);
};
var getDisplayData = function() {
return {"avatar": SHOW_AVATAR,
"collisions": USE_COLLISIONS,
"debug": SHOW_DEBUG_SHAPES,
"solid": SHOW_SOLID_SHAPES};
};
var jointNames = MyAvatar.getJointNames();
function roundFloat(number, decimals) {
var DECIMALS_MULTIPLIER = 10;
var multiplier = Math.pow(DECIMALS_MULTIPLIER, decimals);
var rounded = Math.round(number * multiplier);
return rounded / multiplier;
}
function roundVector(vector, decimals) {
return {x: roundFloat(vector.x, decimals), y: roundFloat(vector.y, decimals), z: roundFloat(vector.z, decimals)};
}
function roundDataValues(decimals) {
var collisions = flowData.collisions;
var physics = flowData.physics;
Object.keys(collisions).forEach(function(key) {
var data = collisions[key];
data.radius = roundFloat(data.radius, decimals);
data.offset = roundVector(data.offset, decimals);
});
Object.keys(physics).forEach(function(key) {
var data = physics[key];
data.damping = roundFloat(data.damping, decimals);
data.delta = roundFloat(data.delta, decimals);
data.gravity = roundFloat(data.gravity, decimals);
data.inertia = roundFloat(data.inertia, decimals);
data.radius = roundFloat(data.radius, decimals);
data.stiffness = roundFloat(data.stiffness, decimals);
});
}
function updateFlowData(catchInitValues) {
flowData = MyAvatar.getFlowData();
if (typeof(flowData) !== "object" || typeof(flowData.collisions) !== "object") {
return;
}
var ROUND_DECIMALS = 4;
var collisionJoints = Object.keys(flowData.collisions);
var inverseScale = 1.0 / avatarScale;
for (var i = 0; i < collisionJoints.length; i++) {
var collision = flowData.collisions[collisionJoints[i]];
collision.radius *= inverseScale;
collision.offset = Vec3.multiply(collision.offset, inverseScale);
}
roundDataValues(ROUND_DECIMALS);
IS_ACTIVE = flowData.active;
USE_COLLISIONS = flowData.colliding;
if (catchInitValues) {
initActive = flowData.active;
initColliding = flowData.colliding;
}
}
function onWebEventReceived(msg) {
var message = JSON.parse(msg);
switch (message.type) {
case MSG_JOINT_INPUT_DATA: {
flowData.physics[message.group][message.name] = message.value;
MyAvatar.useFlow(IS_ACTIVE, USE_COLLISIONS, flowData.physics, flowData.collisions);
break;
}
case MSG_COLLISION_INPUT_DATA: {
var value = message.name === "offset" ? {x: 0.0, y: message.value, z: 0.0} : message.value;
flowData.collisions[message.group][message.name] = value;
MyAvatar.useFlow(IS_ACTIVE, USE_COLLISIONS, flowData.physics, flowData.collisions);
break;
}
case MSG_DISPLAY_DATA: {
switch (message.name) {
case "collisions":
toggleCollisions();
break;
case "debug":
toggleDebugShapes();
break;
case "solid":
toggleSolidShapes();
break;
case "avatar":
toggleAvatarVisible();
break;
}
break;
}
case MSG_DOCUMENT_LOADED: {
MyAvatar.useFlow(true, true);
updateFlowData();
if (initDebugging && !SHOW_DEBUG_SHAPES) {
toggleDebugShapes();
}
createHTMLMenu();
break;
}
case MSG_COLLISION_DATA: {
switch (message.name) {
case "add":
var collisionData = {"type": "sphere", "radius": 0.05, "offset": {"x": 0.0, "y": 0.0, "z": 0.0}};
flowData.collisions[message.value] = collisionData;
MyAvatar.useFlow(IS_ACTIVE, USE_COLLISIONS, flowData.physics, flowData.collisions);
updateFlowData();
tablet.emitScriptEvent(JSON.stringify({
"type": MSG_COLLISION_DATA,
"name": message.value,
"data": collisionData
}));
break;
case "remove":
var jointName = message.value;
collisionDebug.deleteSphere(jointName + "_col");
if (flowData.collisions[jointName] !== undefined) {
delete flowData.collisions[jointName];
MyAvatar.useFlow(IS_ACTIVE, USE_COLLISIONS, flowData.physics, flowData.collisions);
updateFlowData();
}
break;
}
break;
}
}
}
tablet.screenChanged.connect(onScreenChanged);
function createHTMLMenu() {
jointNames = MyAvatar.getJointNames();
tablet.emitScriptEvent(JSON.stringify(
{
"type": MSG_CREATE,
"data": {
"display": getDisplayData(),
"group": flowData.physics,
"collisions": flowData.collisions,
"joints": jointNames
}
}
));
}
function shutdownTabletApp() {
MyAvatar.useFlow(initActive, initColliding);
tablet.removeButton(tabletButton);
if (shown) {
tablet.webEventReceived.disconnect(onWebEventReceived);
tablet.gotoHomeScreen();
}
tablet.screenChanged.disconnect(onScreenChanged);
}
MyAvatar.skeletonChanged.connect(function() {
var MS_AFTER_AVATAR_UPDATE = 200;
collisionDebug.cleanup();
jointDebug.cleanup();
Script.setTimeout(function() {
jointNames = MyAvatar.getJointNames();
avatarScale = MyAvatar.getSensorToWorldScale();
updateFlowData(true);
if (shown) {
manageClick();
}
}, MS_AFTER_AVATAR_UPDATE);
});
MyAvatar.scaleChanged.connect(function() {
avatarScale = MyAvatar.getSensorToWorldScale();
});
Script.update.connect(function() {
if (IS_ACTIVE) {
var groupData = flowData.physics;
var collisionData = flowData.collisions;
var threads = flowData.threads;
var groups = Object.keys(groupData);
var flowPositions = Array(jointNames.length);
var flowCollisionColors = Array(jointNames.length);
var collidingJoints = MyAvatar.getCollidingFlowJoints();
for (var i = 0; i < groups.length; i++) {
var group = groups[i];
var data = groupData[group];
for (var j = 0; j < data.jointIndices.length; j++) {
var index = data.jointIndices[j];
var name = jointNames[index];
var position = MyAvatar.getJointPosition(index);
flowPositions[index] = position;
var colliding = collidingJoints.indexOf(index) > -1;
var color = { red: 255, green: 255, blue: 0 };
if (colliding) {
color.green = 0;
}
flowCollisionColors[index] = color;
var radius = 2.0 * avatarScale * data.radius;
jointDebug.setDebugSphere(name + "_flow", position, radius, color);
}
}
var names = Object.keys(collisionData);
for (i = 0; i < names.length; i++) {
name = names[i];
index = collisionData[name].jointIndex;
var offset = Vec3.multiply(collisionData[name].offset, avatarScale);
radius = avatarScale * collisionData[name].radius;
position = MyAvatar.jointToWorldPoint(offset, index);
collisionDebug.setDebugSphere(name + "_col", position, 2 * radius, {red: 200, green: 10, blue: 50});
}
var threadKeys = Object.keys(threads);
for (i = 0; i < threadKeys.length; i++) {
var thread = threads[threadKeys[i]];
for (j = 1; j < thread.length; j++) {
var index1 = thread[j-1];
var index2 = thread[j];
if (flowPositions[index1] !== undefined && flowPositions[index2] !== undefined) {
var lineName = jointNames[index1] + "_line";
color = flowCollisionColors[index1];
var DEFAULT_LINE_WIDTH = 0.004;
var lineWidth = DEFAULT_LINE_WIDTH * avatarScale;
// We are creating two PolyLines with different normals, to make them more visible from the sides.
var LINE_NORMALS_1 = [{ x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: 1 }];
var LINE_NORMALS_2 = [{ x: 1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }];
jointDebug.setDebugLine(lineName + "_1", LINE_NORMALS_1, flowPositions[index1], flowPositions[index2], color, lineWidth);
jointDebug.setDebugLine(lineName + "_2", LINE_NORMALS_2, flowPositions[index1], flowPositions[index2], color, lineWidth);
}
}
}
}
});
Script.scriptEnding.connect(function () {
collisionDebug.cleanup();
jointDebug.cleanup();
shutdownTabletApp();
});
}, MS_AFTER_LOADING);
}());

Binary file not shown.

After

(image error) Size: 72 B

View file

@ -341,6 +341,15 @@ var metadata = { "applications":
"jsfile": "hmd3rdPerson/app-hmd3rdPerson.js",
"icon": "hmd3rdPerson/icon_inactive_white.png",
"caption": "3rd PERS"
},
{
"isActive": true,
"directory": "flow",
"name": "Flow Bones",
"description": "Effortlessly tweak and tune avatar flow bones.",
"jsfile": "flow/flowAppCpp.js",
"icon": "flow/flow-i.svg",
"caption": "FLOW"
}
]
};