選択したアイテムのハイライト表示
1. ランタイムユーザーに明確な視覚的フィードバックを提供するには、モデルでサブアセンブリまたは部品アイテムを選択したときに、視覚的インジケータをトリガーする必要があります。これにより、ユーザーは正しいアイテムのデータが表示されていることを確認できます。これを実現するために、選択したモデルアイテムにハイライト表示シェーダーを適用します。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. さらに、ユーザーが以前に選択したサブアセンブリから離れた場所をクリックするか、別のサブアセンブリを選択した場合、それに応じてハイライト表示シェーダーを更新する必要があります。これにより、現在選択されているアイテムのみが視覚的に強調され、インタラクション全体で明確さが維持されます。そのため、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. これで、ユーザーが部品リストからアイテムを選択すると、そのアイテムがハイライトされるようになります。特に独自のモデルを操作する場合は、次のコードスニペットで使用されているロジックに細心の注意を払ってください。ロジックは、属性に依存します。これらの属性は、Creo Illustrate で定義されて使用可能であり、ランタイムに部品ごとにロードする必要があります。別のキーまたはカスタム属性を使用して部品固有のデータを表示する場合は、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. 特定の部品名または ID を持たないユーザーは、モデル上で関連するサブアセンブリを直接対話的に選択できます。このシナリオでは、以下を追加します。
// 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];
})
});