mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-18 07:48:48 +02:00
359 lines
11 KiB
QML
359 lines
11 KiB
QML
import Hifi 1.0 as Hifi
|
|
import QtQuick 2.5
|
|
import "../../styles-uit"
|
|
import "../../controls-uit" as HifiControlsUit
|
|
import "../../controls" as HifiControls
|
|
|
|
Rectangle {
|
|
id: root;
|
|
visible: false;
|
|
width: 480
|
|
height: 706
|
|
color: 'white'
|
|
|
|
signal wearableUpdated(var id, int index, var properties);
|
|
signal wearableSelected(var id);
|
|
signal wearableDeleted(string avatarName, var id);
|
|
|
|
signal adjustWearablesOpened(var avatarName);
|
|
signal adjustWearablesClosed(bool status, var avatarName);
|
|
|
|
property bool modified: false;
|
|
Component.onCompleted: {
|
|
modified = false;
|
|
}
|
|
|
|
property var jointNames;
|
|
property string avatarName: ''
|
|
property var wearablesModel;
|
|
|
|
function open(avatar) {
|
|
adjustWearablesOpened(avatar.name);
|
|
|
|
visible = true;
|
|
avatarName = avatar.name;
|
|
wearablesModel = avatar.wearables;
|
|
refresh(avatar);
|
|
}
|
|
|
|
function refresh(avatar) {
|
|
wearablesCombobox.model.clear();
|
|
for(var i = 0; i < avatar.wearables.count; ++i) {
|
|
var wearable = avatar.wearables.get(i).properties;
|
|
for(var j = (wearable.modelURL.length - 1); j >= 0; --j) {
|
|
if(wearable.modelURL[j] === '/') {
|
|
wearable.text = wearable.modelURL.substring(j + 1) + ' [%jointIndex%]'.replace('%jointIndex%', jointNames[wearable.parentJointIndex]);
|
|
break;
|
|
}
|
|
}
|
|
wearablesCombobox.model.append(wearable);
|
|
}
|
|
|
|
wearablesCombobox.currentIndex = 0;
|
|
}
|
|
|
|
function refreshWearable(wearableID, wearableIndex, properties, updateUI) {
|
|
if(wearableIndex === -1) {
|
|
wearableIndex = wearablesCombobox.model.findIndexById(wearableID);
|
|
}
|
|
|
|
var wearable = wearablesCombobox.model.get(wearableIndex);
|
|
|
|
if(!wearable) {
|
|
return;
|
|
}
|
|
|
|
var wearableModelItemProperties = wearablesModel.get(wearableIndex).properties;
|
|
|
|
for(var prop in properties) {
|
|
wearable[prop] = properties[prop];
|
|
wearableModelItemProperties[prop] = wearable[prop];
|
|
|
|
if(updateUI) {
|
|
if(prop === 'localPosition') {
|
|
position.set(wearable[prop]);
|
|
} else if(prop === 'localRotationAngles') {
|
|
rotation.set(wearable[prop]);
|
|
} else if(prop === 'dimensions') {
|
|
scalespinner.set(wearable[prop].x / wearable.naturalDimensions.x);
|
|
}
|
|
}
|
|
}
|
|
|
|
wearablesModel.setProperty(wearableIndex, 'properties', wearableModelItemProperties);
|
|
}
|
|
|
|
function getCurrentWearable() {
|
|
return wearablesCombobox.model.get(wearablesCombobox.currentIndex)
|
|
}
|
|
|
|
function selectWearableByID(entityID) {
|
|
for(var i = 0; i < wearablesCombobox.model.count; ++i) {
|
|
var wearable = wearablesCombobox.model.get(i);
|
|
if(wearable.id === entityID) {
|
|
wearablesCombobox.currentIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function close(status) {
|
|
visible = false;
|
|
adjustWearablesClosed(status, avatarName);
|
|
}
|
|
|
|
HifiConstants { id: hifi }
|
|
|
|
// This object is always used in a popup.
|
|
// This MouseArea is used to prevent a user from being
|
|
// able to click on a button/mouseArea underneath the popup.
|
|
MouseArea {
|
|
anchors.fill: parent;
|
|
propagateComposedEvents: false;
|
|
hoverEnabled: true;
|
|
}
|
|
|
|
Column {
|
|
anchors.top: parent.top
|
|
anchors.topMargin: 15
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
spacing: 20
|
|
width: parent.width - 30 * 2
|
|
|
|
HifiControlsUit.ComboBox {
|
|
id: wearablesCombobox
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
comboBox.textRole: "text"
|
|
|
|
model: ListModel {
|
|
function findIndexById(id) {
|
|
|
|
for(var i = 0; i < count; ++i) {
|
|
var wearable = get(i);
|
|
if(wearable.id === id) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
comboBox.onCurrentIndexChanged: {
|
|
var currentWearable = getCurrentWearable();
|
|
|
|
if(currentWearable) {
|
|
position.set(currentWearable.localPosition);
|
|
rotation.set(currentWearable.localRotationAngles);
|
|
scalespinner.set(currentWearable.dimensions.x / currentWearable.naturalDimensions.x)
|
|
|
|
wearableSelected(currentWearable.id);
|
|
}
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: parent.width
|
|
spacing: 5
|
|
|
|
Row {
|
|
spacing: 20
|
|
|
|
// TextStyle5
|
|
FiraSansSemiBold {
|
|
id: positionLabel
|
|
size: 22;
|
|
text: "Position"
|
|
}
|
|
|
|
// TextStyle7
|
|
FiraSansRegular {
|
|
size: 18;
|
|
lineHeightMode: Text.FixedHeight
|
|
lineHeight: 16.9;
|
|
text: "m"
|
|
anchors.verticalCenter: positionLabel.verticalCenter
|
|
}
|
|
}
|
|
|
|
Vector3 {
|
|
id: position
|
|
backgroundColor: "lightgray"
|
|
|
|
function set(localPosition) {
|
|
notify = false;
|
|
xvalue = localPosition.x
|
|
yvalue = localPosition.y
|
|
zvalue = localPosition.z
|
|
notify = true;
|
|
}
|
|
|
|
function notifyPositionChanged() {
|
|
modified = true;
|
|
var properties = {
|
|
localPosition: { 'x' : xvalue, 'y' : yvalue, 'z' : zvalue }
|
|
};
|
|
|
|
wearableUpdated(getCurrentWearable().id, wearablesCombobox.currentIndex, properties);
|
|
}
|
|
|
|
property bool notify: false;
|
|
|
|
onXvalueChanged: if(notify) notifyPositionChanged();
|
|
onYvalueChanged: if(notify) notifyPositionChanged();
|
|
onZvalueChanged: if(notify) notifyPositionChanged();
|
|
|
|
decimals: 2
|
|
realFrom: -10
|
|
realTo: 10
|
|
realStepSize: 0.01
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: parent.width
|
|
spacing: 5
|
|
|
|
Row {
|
|
spacing: 20
|
|
|
|
// TextStyle5
|
|
FiraSansSemiBold {
|
|
id: rotationLabel
|
|
size: 22;
|
|
text: "Rotation"
|
|
}
|
|
|
|
// TextStyle7
|
|
FiraSansRegular {
|
|
size: 18;
|
|
lineHeightMode: Text.FixedHeight
|
|
lineHeight: 16.9;
|
|
text: "deg"
|
|
anchors.verticalCenter: rotationLabel.verticalCenter
|
|
}
|
|
}
|
|
|
|
Vector3 {
|
|
id: rotation
|
|
backgroundColor: "lightgray"
|
|
|
|
function set(localRotationAngles) {
|
|
notify = false;
|
|
xvalue = localRotationAngles.x
|
|
yvalue = localRotationAngles.y
|
|
zvalue = localRotationAngles.z
|
|
notify = true;
|
|
}
|
|
|
|
function notifyRotationChanged() {
|
|
modified = true;
|
|
var properties = {
|
|
localRotationAngles: { 'x' : xvalue, 'y' : yvalue, 'z' : zvalue }
|
|
};
|
|
|
|
wearableUpdated(getCurrentWearable().id, wearablesCombobox.currentIndex, properties);
|
|
}
|
|
|
|
property bool notify: false;
|
|
|
|
onXvalueChanged: if(notify) notifyRotationChanged();
|
|
onYvalueChanged: if(notify) notifyRotationChanged();
|
|
onZvalueChanged: if(notify) notifyRotationChanged();
|
|
|
|
decimals: 0
|
|
realFrom: -180
|
|
realTo: 180
|
|
realStepSize: 1
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: parent.width
|
|
spacing: 5
|
|
|
|
// TextStyle5
|
|
FiraSansSemiBold {
|
|
size: 22;
|
|
text: "Scale"
|
|
}
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: childrenRect.height
|
|
|
|
HifiControlsUit.SpinBox {
|
|
id: scalespinner
|
|
decimals: 2
|
|
realStepSize: 0.1
|
|
realFrom: 0.1
|
|
realTo: 3.0
|
|
realValue: 1.0
|
|
backgroundColor: "lightgray"
|
|
width: position.spinboxWidth
|
|
colorScheme: hifi.colorSchemes.light
|
|
|
|
property bool notify: false;
|
|
onValueChanged: if(notify) notifyScaleChanged();
|
|
|
|
function set(value) {
|
|
notify = false;
|
|
realValue = value
|
|
notify = true;
|
|
}
|
|
|
|
function notifyScaleChanged() {
|
|
modified = true;
|
|
var currentWearable = getCurrentWearable();
|
|
var naturalDimensions = currentWearable.naturalDimensions;
|
|
|
|
var properties = {
|
|
dimensions: {
|
|
'x' : realValue * naturalDimensions.x,
|
|
'y' : realValue * naturalDimensions.y,
|
|
'z' : realValue * naturalDimensions.z
|
|
}
|
|
};
|
|
|
|
wearableUpdated(currentWearable.id, wearablesCombobox.currentIndex, properties);
|
|
}
|
|
}
|
|
|
|
HifiControlsUit.Button {
|
|
fontSize: 18
|
|
height: 40
|
|
anchors.right: parent.right
|
|
color: hifi.buttons.red;
|
|
colorScheme: hifi.colorSchemes.light;
|
|
text: "TAKE IT OFF"
|
|
onClicked: wearableDeleted(root.avatarName, getCurrentWearable().id);
|
|
enabled: wearablesCombobox.model.count !== 0
|
|
anchors.verticalCenter: scalespinner.verticalCenter
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
DialogButtons {
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: 30
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 30
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 30
|
|
|
|
yesText: "SAVE"
|
|
noText: "CANCEL"
|
|
|
|
onYesClicked: function() {
|
|
root.close(true);
|
|
}
|
|
|
|
onNoClicked: function() {
|
|
root.close(false);
|
|
}
|
|
}
|
|
}
|