mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 04:57:58 +02:00
Merge pull request #1618 from AleziaKurdis/createApp_2025_06_Bundle
Create app: Properties Tab: Add "tags" properties and arrayOfStrings field type to support it.
This commit is contained in:
commit
1238aa1297
3 changed files with 221 additions and 4 deletions
|
@ -698,6 +698,9 @@
|
||||||
"renderWithZones": {
|
"renderWithZones": {
|
||||||
"tooltip": "If set, this entity will only render when your avatar is inside of a zone in this list."
|
"tooltip": "If set, this entity will only render when your avatar is inside of a zone in this list."
|
||||||
},
|
},
|
||||||
|
"tags": {
|
||||||
|
"tooltip": "A set of tags describing this entity that can be used with the API."
|
||||||
|
},
|
||||||
"groupCulled": {
|
"groupCulled": {
|
||||||
"tooltip": "If false, individual pieces of the entity may be culled by the render engine. If true, either the entire entity will be culled, or it won't at all."
|
"tooltip": "If false, individual pieces of the entity may be culled by the render engine. If true, either the entire entity will be culled, or it won't at all."
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,6 +23,8 @@ const ENTITY_HOST_TYPE_COLOR_LOCAL = "#f0d769";
|
||||||
|
|
||||||
const NO_SELECTION = ",";
|
const NO_SELECTION = ",";
|
||||||
|
|
||||||
|
const MAX_TAGS_PER_ROWS = 5;
|
||||||
|
|
||||||
const PROPERTY_SPACE_MODE = Object.freeze({
|
const PROPERTY_SPACE_MODE = Object.freeze({
|
||||||
ALL: 0,
|
ALL: 0,
|
||||||
LOCAL: 1,
|
LOCAL: 1,
|
||||||
|
@ -154,7 +156,13 @@ const GROUPS = [
|
||||||
label: "Render With Zones",
|
label: "Render With Zones",
|
||||||
type: "multipleZonesSelection",
|
type: "multipleZonesSelection",
|
||||||
propertyID: "renderWithZones",
|
propertyID: "renderWithZones",
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
label: "Tags",
|
||||||
|
type: "arrayOfStrings",
|
||||||
|
propertyID: "tags",
|
||||||
|
useStringColor: true,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1126,7 +1134,7 @@ const GROUPS = [
|
||||||
vec2Type: "xyz",
|
vec2Type: "xyz",
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1,
|
max: 1,
|
||||||
step: 0.1,
|
step: 0.005,
|
||||||
decimals: 4,
|
decimals: 4,
|
||||||
subLabels: [ "x", "y" ],
|
subLabels: [ "x", "y" ],
|
||||||
propertyID: "materialMappingPos",
|
propertyID: "materialMappingPos",
|
||||||
|
@ -1135,7 +1143,7 @@ const GROUPS = [
|
||||||
label: "Material Scale",
|
label: "Material Scale",
|
||||||
type: "vec2",
|
type: "vec2",
|
||||||
vec2Type: "xyz",
|
vec2Type: "xyz",
|
||||||
step: 0.1,
|
step: 0.005,
|
||||||
decimals: 4,
|
decimals: 4,
|
||||||
subLabels: [ "x", "y" ],
|
subLabels: [ "x", "y" ],
|
||||||
propertyID: "materialMappingScale",
|
propertyID: "materialMappingScale",
|
||||||
|
@ -2297,6 +2305,8 @@ function getPropertyInputElement(propertyID) {
|
||||||
return property.elInput;
|
return property.elInput;
|
||||||
case 'multipleZonesSelection':
|
case 'multipleZonesSelection':
|
||||||
return property.elInput;
|
return property.elInput;
|
||||||
|
case 'arrayOfStrings':
|
||||||
|
return property.elInput;
|
||||||
case 'number-draggable':
|
case 'number-draggable':
|
||||||
return property.elNumber.elInput;
|
return property.elNumber.elInput;
|
||||||
case 'rect':
|
case 'rect':
|
||||||
|
@ -2464,6 +2474,12 @@ function resetProperties() {
|
||||||
setZonesSelectionData(property.elInput, false);
|
setZonesSelectionData(property.elInput, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'arrayOfStrings': {
|
||||||
|
property.elInput.classList.remove('multi-diff');
|
||||||
|
property.elInput.value = "[]";
|
||||||
|
setArrayOfStringsUi(property.elInput.id, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'childList': {
|
case 'childList': {
|
||||||
setChildListData(property.elInput, undefined, "");
|
setChildListData(property.elInput, undefined, "");
|
||||||
break;
|
break;
|
||||||
|
@ -3716,6 +3732,10 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI
|
||||||
property.elInput = createZonesSelection(property, elProperty);
|
property.elInput = createZonesSelection(property, elProperty);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'arrayOfStrings': {
|
||||||
|
property.elInput = createArrayOfStrings(property, elProperty);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'childList': {
|
case 'childList': {
|
||||||
property.elInput = createChildList(property, elProperty);
|
property.elInput = createChildList(property, elProperty);
|
||||||
break;
|
break;
|
||||||
|
@ -4834,6 +4854,155 @@ function setZonesSelectionData(element, isEditable) {
|
||||||
displaySelectedZones(element.id, isEditable);
|
displaySelectedZones(element.id, isEditable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARRAY-OF-STRINGS FUNCTIONS
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createArrayOfStrings(property, elProperty) {
|
||||||
|
let propertyData = property.data;
|
||||||
|
let elementID = property.elementID;
|
||||||
|
elProperty.className = "arrayOfStrings";
|
||||||
|
let elInput = document.createElement('input');
|
||||||
|
elInput.setAttribute("id", elementID);
|
||||||
|
elInput.setAttribute("type", "hidden");
|
||||||
|
elInput.setAttribute("useStringColor", propertyData.useStringColor);
|
||||||
|
elInput.className = "hiddenArrayOfStrings";
|
||||||
|
|
||||||
|
let elArrayOfStringsSelector = document.createElement('div');
|
||||||
|
elArrayOfStringsSelector.setAttribute("id", "arrayOfStrings-selector-" + elementID);
|
||||||
|
|
||||||
|
let elMultiDiff = document.createElement('span');
|
||||||
|
elMultiDiff.className = "multi-diff";
|
||||||
|
|
||||||
|
elProperty.appendChild(elInput);
|
||||||
|
elProperty.appendChild(elArrayOfStringsSelector);
|
||||||
|
elProperty.appendChild(elMultiDiff);
|
||||||
|
|
||||||
|
return elInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setArrayOfStringsUi(propertyId, isEditable) {
|
||||||
|
let i, listedStringsInner, hiddenData, isMultiple, useStringColor, tagStyle;
|
||||||
|
hiddenData = document.getElementById(propertyId).value;
|
||||||
|
useStringColor = document.getElementById(propertyId).getAttribute('useStringColor').toLowerCase() === "true";
|
||||||
|
if (JSON.stringify(hiddenData) === '"undefined"') {
|
||||||
|
isMultiple = true;
|
||||||
|
hiddenData = "[]";
|
||||||
|
} else {
|
||||||
|
isMultiple = false;
|
||||||
|
}
|
||||||
|
listedStringsInner = "<div class='arrayOfStringsContainer'>";
|
||||||
|
let selectedStrings = JSON.parse(hiddenData);
|
||||||
|
if (selectedStrings.length === 0) {
|
||||||
|
if (isMultiple) {
|
||||||
|
listedStringsInner += "<br>"; //or anything saying we dont suport multiple selection, but we might by the list with bulk actions.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selectedStrings.sort();
|
||||||
|
let counter = 0;
|
||||||
|
for (i = 0; i < selectedStrings.length; i++) {
|
||||||
|
tagStyle = "";
|
||||||
|
if (useStringColor) {
|
||||||
|
tagStyle = " style='color:#bbbbbb; background-color:" + getColorOfString(selectedStrings[i]) + ";'";
|
||||||
|
}
|
||||||
|
if (isEditable) {
|
||||||
|
listedStringsInner += "<div class='arrayOfStringsTags'" + tagStyle + ">" + selectedStrings[i] + " ";
|
||||||
|
listedStringsInner += "<span class='arrayOfStringsTagsRemove' onClick='removeElementFromArrayOfStrings(" + '"' + propertyId + '"' + ", " + '"' + selectedStrings[i] + '"' + ");' >✖</span>"
|
||||||
|
listedStringsInner += "</div>";
|
||||||
|
} else {
|
||||||
|
listedStringsInner += "<div class='arrayOfStringsTags'" + tagStyle + ">" + selectedStrings[i] + "</div>";
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
if (counter === MAX_TAGS_PER_ROWS) {
|
||||||
|
listedStringsInner += "<br>";
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isEditable && !isMultiple) {
|
||||||
|
let addComponent = "<div class='arrayOfStringsAddComponentContainer'><input class='arrayOfStringsStringToAdd' type='text' id='arrayOfStringsStringToAdd-" + propertyId + "'>";
|
||||||
|
addComponent += " <input type='button' class='glyph' value = 'K' id='arrayOfStringsAddButton-" + propertyId + "' onClick='addElementToArrayOfStrings(" + '"' + propertyId + '", "';
|
||||||
|
addComponent += "arrayOfStringsStringToAdd-" + propertyId + '"' + ");'>";
|
||||||
|
addComponent += "</div>";
|
||||||
|
listedStringsInner += addComponent;
|
||||||
|
}
|
||||||
|
listedStringsInner += "</div>";
|
||||||
|
document.getElementById("arrayOfStrings-selector-" + propertyId).innerHTML = listedStringsInner;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeElementFromArrayOfStrings(propertyId, stringText) {
|
||||||
|
let hiddenField = document.getElementById(propertyId);
|
||||||
|
if (JSON.stringify(hiddenField.value) === '"undefined"') {
|
||||||
|
hiddenField.value = "[]";
|
||||||
|
}
|
||||||
|
let selectedStrings = JSON.parse(hiddenField.value);
|
||||||
|
let index = selectedStrings.indexOf(stringText);
|
||||||
|
if (index > -1) {
|
||||||
|
selectedStrings.splice(index, 1);
|
||||||
|
}
|
||||||
|
hiddenField.value = JSON.stringify(selectedStrings);
|
||||||
|
setArrayOfStringsUi(propertyId, true);
|
||||||
|
let propertyName = propertyId.replace("property-", "");
|
||||||
|
propertyName = propertyName.replace("-", ".");
|
||||||
|
updateProperty(propertyName, selectedStrings, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addElementToArrayOfStrings(propertyId, elementToGetText) {
|
||||||
|
let stringText = document.getElementById(elementToGetText).value;
|
||||||
|
if (stringText === "") {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
let hiddenField = document.getElementById(propertyId);
|
||||||
|
if (JSON.stringify(hiddenField.value) === '"undefined"') {
|
||||||
|
hiddenField.value = "[]";
|
||||||
|
}
|
||||||
|
let selectedStrings = JSON.parse(hiddenField.value);
|
||||||
|
if (!selectedStrings.includes(stringText)) {
|
||||||
|
selectedStrings.push(stringText);
|
||||||
|
}
|
||||||
|
hiddenField.value = JSON.stringify(selectedStrings);
|
||||||
|
setArrayOfStringsUi(propertyId, true);
|
||||||
|
let propertyName = propertyId.replace("property-", "");
|
||||||
|
propertyName = propertyName.replace("-", ".");
|
||||||
|
updateProperty(propertyName, selectedStrings, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColorOfString(input) {
|
||||||
|
let sum = 0;
|
||||||
|
for (let i = 0; i < input.length; i++) {
|
||||||
|
sum += input.charCodeAt(i);
|
||||||
|
}
|
||||||
|
let hue = sum % 360;
|
||||||
|
return hslToHex(hue, 100, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hslToHex(h, s, l) {
|
||||||
|
s /= 100;
|
||||||
|
l /= 100;
|
||||||
|
const c = (1 - Math.abs(2 * l - 1)) * s;
|
||||||
|
const x = c * (1 - Math.abs((h / 60) % 2 - 1));
|
||||||
|
const m = l - c / 2;
|
||||||
|
let r = 0, g = 0, b = 0;
|
||||||
|
if (0 <= h && h < 60) {
|
||||||
|
[r, g, b] = [c, x, 0];
|
||||||
|
} else if (60 <= h && h < 120) {
|
||||||
|
[r, g, b] = [x, c, 0];
|
||||||
|
} else if (120 <= h && h < 180) {
|
||||||
|
[r, g, b] = [0, c, x];
|
||||||
|
} else if (180 <= h && h < 240) {
|
||||||
|
[r, g, b] = [0, x, c];
|
||||||
|
} else if (240 <= h && h < 300) {
|
||||||
|
[r, g, b] = [x, 0, c];
|
||||||
|
} else if (300 <= h && h < 360) {
|
||||||
|
[r, g, b] = [c, 0, x];
|
||||||
|
}
|
||||||
|
const toHex = (n) => {
|
||||||
|
const hex = Math.round((n + m) * 255).toString(16);
|
||||||
|
return hex.padStart(2, '0');
|
||||||
|
};
|
||||||
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CHILD ENTITIES FUNCTIONS
|
* CHILD ENTITIES FUNCTIONS
|
||||||
|
@ -5530,7 +5699,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'multipleZonesSelection': {
|
case 'multipleZonesSelection': {
|
||||||
property.elInput.value = JSON.stringify(propertyValue);
|
property.elInput.value = JSON.stringify(propertyValue);
|
||||||
if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) {
|
if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) {
|
||||||
setZonesSelectionData(property.elInput, false);
|
setZonesSelectionData(property.elInput, false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5538,6 +5707,15 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'arrayOfStrings': {
|
||||||
|
property.elInput.value = JSON.stringify(propertyValue);
|
||||||
|
if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) {
|
||||||
|
setArrayOfStringsUi(property.elInput.id, false);
|
||||||
|
} else {
|
||||||
|
setArrayOfStringsUi(property.elInput.id, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'childList': {
|
case 'childList': {
|
||||||
let parentID = selections[0].properties.parentID;
|
let parentID = selections[0].properties.parentID;
|
||||||
if (selections.length !== 1 || parentID === UUID_NONE) {
|
if (selections.length !== 1 || parentID === UUID_NONE) {
|
||||||
|
|
|
@ -335,6 +335,10 @@ input[type="text"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.arrayOfStringsStringToAdd {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
input.multi-diff:not(:focus) + span.multi-diff,
|
input.multi-diff:not(:focus) + span.multi-diff,
|
||||||
textarea.multi-diff:not(:focus) + span.multi-diff,
|
textarea.multi-diff:not(:focus) + span.multi-diff,
|
||||||
.draggable-number.multi-diff>input:not(:focus)+span.multi-diff,
|
.draggable-number.multi-diff>input:not(:focus)+span.multi-diff,
|
||||||
|
@ -2292,3 +2296,35 @@ font.viewParentIcon {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.arrayOfStringsContainer {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.arrayOfStringsAddComponentContainer {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.arrayOfStringsTags {
|
||||||
|
color: #000000;
|
||||||
|
font-family: FiraSans-SemiBold;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 5px 8px 5px 8px;
|
||||||
|
margin: 2px;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #dddddd;
|
||||||
|
border: none;
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.arrayOfStringsTagsRemove {
|
||||||
|
color: #777777;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.arrayOfStringsTagsRemove:hover {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue