mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 16:30:10 +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": {
|
||||
"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": {
|
||||
"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 MAX_TAGS_PER_ROWS = 5;
|
||||
|
||||
const PROPERTY_SPACE_MODE = Object.freeze({
|
||||
ALL: 0,
|
||||
LOCAL: 1,
|
||||
|
@ -154,7 +156,13 @@ const GROUPS = [
|
|||
label: "Render With Zones",
|
||||
type: "multipleZonesSelection",
|
||||
propertyID: "renderWithZones",
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Tags",
|
||||
type: "arrayOfStrings",
|
||||
propertyID: "tags",
|
||||
useStringColor: true,
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -1126,7 +1134,7 @@ const GROUPS = [
|
|||
vec2Type: "xyz",
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.1,
|
||||
step: 0.005,
|
||||
decimals: 4,
|
||||
subLabels: [ "x", "y" ],
|
||||
propertyID: "materialMappingPos",
|
||||
|
@ -1135,7 +1143,7 @@ const GROUPS = [
|
|||
label: "Material Scale",
|
||||
type: "vec2",
|
||||
vec2Type: "xyz",
|
||||
step: 0.1,
|
||||
step: 0.005,
|
||||
decimals: 4,
|
||||
subLabels: [ "x", "y" ],
|
||||
propertyID: "materialMappingScale",
|
||||
|
@ -2297,6 +2305,8 @@ function getPropertyInputElement(propertyID) {
|
|||
return property.elInput;
|
||||
case 'multipleZonesSelection':
|
||||
return property.elInput;
|
||||
case 'arrayOfStrings':
|
||||
return property.elInput;
|
||||
case 'number-draggable':
|
||||
return property.elNumber.elInput;
|
||||
case 'rect':
|
||||
|
@ -2464,6 +2474,12 @@ function resetProperties() {
|
|||
setZonesSelectionData(property.elInput, false);
|
||||
break;
|
||||
}
|
||||
case 'arrayOfStrings': {
|
||||
property.elInput.classList.remove('multi-diff');
|
||||
property.elInput.value = "[]";
|
||||
setArrayOfStringsUi(property.elInput.id, false);
|
||||
break;
|
||||
}
|
||||
case 'childList': {
|
||||
setChildListData(property.elInput, undefined, "");
|
||||
break;
|
||||
|
@ -3716,6 +3732,10 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI
|
|||
property.elInput = createZonesSelection(property, elProperty);
|
||||
break;
|
||||
}
|
||||
case 'arrayOfStrings': {
|
||||
property.elInput = createArrayOfStrings(property, elProperty);
|
||||
break;
|
||||
}
|
||||
case 'childList': {
|
||||
property.elInput = createChildList(property, elProperty);
|
||||
break;
|
||||
|
@ -4834,6 +4854,155 @@ function setZonesSelectionData(element, 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
|
||||
|
@ -5530,7 +5699,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) {
|
|||
break;
|
||||
}
|
||||
case 'multipleZonesSelection': {
|
||||
property.elInput.value = JSON.stringify(propertyValue);
|
||||
property.elInput.value = JSON.stringify(propertyValue);
|
||||
if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) {
|
||||
setZonesSelectionData(property.elInput, false);
|
||||
} else {
|
||||
|
@ -5538,6 +5707,15 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) {
|
|||
}
|
||||
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': {
|
||||
let parentID = selections[0].properties.parentID;
|
||||
if (selections.length !== 1 || parentID === UUID_NONE) {
|
||||
|
|
|
@ -335,6 +335,10 @@ input[type="text"] {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
input.arrayOfStringsStringToAdd {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
input.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,
|
||||
|
@ -2292,3 +2296,35 @@ font.viewParentIcon {
|
|||
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