Mettre en surbrillance les éléments sélectionnés
1. Pour fournir un retour visuel clair à l'utilisateur durant l'exécution, la sélection d'un élément de sous-assemblage ou de pièce dans le modèle doit déclencher un indicateur visuel. Cela permet aux utilisateurs de confirmer qu'ils visualisent les données pour le bon élément. Pour ce faire, nous allons appliquer le nuanceur highlight à l'élément de modèle sélectionné. Ajoutez les éléments suivants à Visualization.js :
// call this function to highlight the list of selected parts
//
var highlightParts = (selectedList, modelId) => {
var highlightedList = [];
// run over all the items in the list and assign the highlight shader
selectedList.forEach( (partId) => {
var renderingPartId = modelId + "-" + partId;
var shader = "highlight;r f 1;g f 0.5;b f 0.25;a f 1" + (twx.app.isPreview() ? ";virtualMode f 1.0":"");
tml3dRenderer.setProperties(renderingPartId, { shader: shader, opacity: 1.0, hidden: false });
// and keep a record of what we highlighted - so that we wan undo it later
//
highlightedList.push(renderingPartId);
});
return highlightedList;
}
2. En outre, lorsque l'utilisateur clique en dehors d'un sous-assemblage précédemment sélectionné ou en sélectionne un autre, le nuanceur highlight doit être mis à jour en conséquence. Ainsi, seul l'élément actuellement sélectionné reste visuellement en évidence, ce qui permet de conserver la clarté de l'interaction. Par conséquent, vous ajouterez également les éléments suivants à Visualization.js :
// call this function to clear the highlights
//
var highlightReset = (highlightedList) => {
// run over all the items in the list and unsasign the shader
//
highlightedList.forEach( (modelIdpartId) => {
tml3dRenderer.setProperties(modelIdpartId,{ shader:"", opacity: 0.2, hidden: !twx.app.isPreview() });
});
return [];
}
3. Désormais, lorsqu'un utilisateur sélectionne un élément dans la liste de pièces, cet élément doit être mis en surbrillance. Portez une attention particulière à la logique utilisée dans l'extrait de code suivant, surtout si vous travaillez avec votre propre modèle. La logique repose sur des attributs qui doivent être définis et disponibles dans Creo Illustrate, et chargés au moment de l'exécution pour chaque pièce. Si vous utilisez une clé différente ou des attributs personnalisés pour afficher des données spécifiques à une pièce, veillez à mettre à jour en conséquence les références d'attribut dans le code suivant afin qu'elles correspondent à la structure de votre modèle dans Visualization.js :
// used to track which items are highlighted
$scope.lit = [];
// called when the user taps on a property in the named list, or taps on a part in the view - this changes the 'current' field
//
$scope.$watch(
() => {
return ($scope.view.wdg.partsList.list != undefined &&
$scope.view.wdg.partsList.list.current != undefined) ? JSON.stringify($scope.view.wdg.partsList.list.current) : "";
},
//value == 'currentSelectedPart',
(value) => {
highlightReset($scope.lit);
var partNumber = JSON.parse(value);
// first of all, lets get all the metadata values for this selected item
//
var plist = [];
PTC.Metadata.fromId(partNumber.model)
.then ( (metadata) => {
// find all the items with this partnumber
//
plist = metadata.find(metadataKey).like(partNumber.name);
if (plist == undefined)
{
return;
}
// highlight those items
//
$scope.lit = highlightParts(plist.getSelected(), partNumber.model);
// now find some interesting properties
//
var interestingProperties = ["cost","supplier","weight","partNumber"];
// this function (declared inline) is used to get the property values (see above) for eeach of the items
// in the previously acquired partnmubered plist - it will iterate through each item (idpath) and get the
// properties for each item; if found, they are captured into an array of name=value pairs.
//
var getInteresting = (ip) => {
var ilist = ip;
return function(idpath) {
const res = this.get(idpath, ilist);
var retobj = { path:idpath };
if (res != undefined && res.length === ilist.length) for (var p=0;p<ilist.length;p++) {
// add each result as a new property in the return body
retobj[ilist[p]] = res[p];
}
return retobj;
}
}
// get a list of items with this property set
//
plist = plist.getSelected(getInteresting(interestingProperties));
// helper function to get and format the properties - this generates a list of name|value pairs
//
var getNameValues = (items) => {
var nv = [];
items.forEach( (i) => {
Object.keys(i).forEach( (j) =>{
if (interestingProperties.includes(j)) nv.push({name:j, value:i[j]});
})
})
return nv;
}
// we need to turn this into a list of item/name/value
//
$scope.view.wdg.propertiesList.data = getNameValues(plist);
//
// and show the popup
//
twx.app.fn.triggerWidgetService("propertyPopup", 'showpopup')
})
}
);
4. Dans les cas où l'utilisateur ne dispose pas du nom ou de l'ID de pièce spécifique, il peut sélectionner de manière interactive le sous-assemblage approprié directement sur le modèle. Pour ce scénario, ajoutez les éléments suivants :
// called if the user taps on a part
$scope.$on("userpick", (event, model, type, args) => {
PTC.Metadata.fromId(model)
.then ( (metadata) => {
var pathId = JSON.parse(args).occurrence;
var sid = metadata.get(pathId, metadataKey);
var findMetaDataKey = (p) => {
// simple inline closure that will test if the item name is the value specificed (p in this case)
// this gets called for all items in the list (see findIndex, below)
//
return function(v) { return v.name == p; }
}
// work out which row we need to select
//
var fid = $scope.view.wdg.partsList.list.findIndex(findMetaDataKey(sid));
// return call here if not found
// ... and mark it as selected
//
$scope.view.wdg.partsList.list.forEach( (v,i) => { v._isSelected = (i == fid) });
// and get the row to highlight in 3d
//
$scope.view.wdg.partsList.list.current = $scope.view.wdg.partsList.list.filter( (v,i) => { return i == fid })[0];
})
});