Closed ezmobivietnam closed 1 year ago
Sheets display drawings and spatial views via view attachments. A view attachment is like a snapshot image that is set up when deciding how the view should look when displayed on the sheet. Each attachment specifies its own view, and each view has its own category selector, subcategory overrides, view flags, etc which define the symbology overrides to apply when drawing that view onto the sheet. If the sheet view's own symbology overrides were applied to the attached views, then the attached views would not render properly - e.g., turning off a category or constructions in the sheet view would turn them off in the attached views as well.
Please explain the goal - i.e., user-facing feature/behavior, not a technical implementation detail - that you are trying to achieve so we can determine an appropriate solution.
The use case would be below: On the Civil frontstage, the user would only want to see the sheets, not the drawings. So the drawings would not be displayed on the Civil frontstage. And when the user opens a sheet in the second view to review the design and selects an element on the sheet, he/she would like to see the 3D representation properties of the selected 2D element instead of seeing the 2D properties as current.
So a solution for this use case is: when the user selects a 2D element, the app will try to look up its 3D representation element which is displaying on a 3D view (the main view/first view), and select that 3D element then. As a result, the properties of the 3D element will be displayed on the Property widget accordingly. However, when the 3D element on the main view was selected, because the unified selection is enabled, the current selection on the sheet view was lost so he/she cannot know which one is being selected. To resolve this issue, we would like to override/change the default color of the selected 2D element from black to another color such as RED so that the user could be aware of which 2D element has just been selected.
Another use case is to sync a 2D sheet model with a 3D model. When a certain condition meets, some 2D elements in the sheet could be hidden intentionally.
when the user selects a 2D element, the app will try to look up its 3D representation element which is displaying on a 3D view (the main view/first view), and select that 3D element then. As a result, the properties of the 3D element will be displayed on the Property widget accordingly.
There's an option to tell the property grid to load properties of the related 3d element instead of the selected 2d one. Let me know if that works for you and you need guidance on how to set that up.
@grigasp I believe that Binh (@ezmobivietnam) had already tried that, but it would select the element in the Drawing model, not the element from the 3D model. Could you confirm Binh?
@grigasp I believe that Binh (@ezmobivietnam) had already tried that, but it would select the element in the Drawing model, not the element from the 3D model. Could you confirm Binh?
Do you need 3d element to be selected or to see it's properties in the property grid? Or both?
Hi @grigasp , Thanks so much for your help!
I need the 2D element to be selected and the properties of its 3D representation element will be displayed on the property grid/widget.
E.g. What I have been trying to do is when the user selects a 2D element in the sheet view then the app will display the properties of the 3D representation element that is associated with the selected 2D element on the properties widget. And the selection/focus still stays on the sheet view (not move to the 3D view).
Below is what I have tried to do to fulfill the requirement above.
When an element of a sheet is selected, I will convert and add its 3D representation ID to the selection set of the imodel. As a result, the properties of the selected 3D element will be displayed on the Property widget. However, I led to the two issues below:
Thanks!
I updated the defect title and removed the display
label. This problem sounds like it should be solved using the presentation system, not by changing the selection set under the hood and trying to fake a hilite effect on the no-longer-selected 2d element.
@pmconne , @grigasp , how would I resolve my issue by using the presentation system? Please give me a hint. I still don't have any ideas at the moment. Thanks!
I can't answer that. Hopefully @grigasp can. Please show the code you used when you "already tried that" as @simnorm mentioned.
Here is a piece of the code: export class SheetViewerSelectionTool extends SelectionTool { public static override toolId = "SheetSelectionTool";
// A map from 2D element ID (key) to 3D element ID (value) private _elementIdMap = new Map<string, string>();
public static override startTool(): Promise
public async onRestartTool(): Promise
public override async onPostInstall(): Promise
public override async onCleanup(): Promise
public override async onDataButtonUp(
ev: BeButtonEvent
): Promise
const hit = await IModelApp.locateManager.doLocate(
new LocateResponse(),
true,
ev.point,
ev.viewport,
ev.inputSource
);
if (hit && hit.isElementHit && ev.viewport?.view.is2d()) {
const element2dId = hit.sourceId;
this.overrideElements(element2dId, ev.viewport);
}
return eventHandled;
}
// override this function to convert the selection id from 2d to 3d while
// trying to minimize the change to the original code.
public async processSelection(
elementId: Id64Arg,
process: SelectionProcessing
): Promise
if (!converted3dIdSet.size) {
return false;
}
return super.updateSelection(converted3dIdSet, process);
}
private overrideElements(elementIds: Id64Arg, vp: Viewport) { const emphasizer = EmphasizeElements.getOrCreate(vp); emphasizer.clearOverriddenElements(vp); emphasizer.overrideElements( elementIds, vp, ColorDef.blue, FeatureOverrideType.ColorOnly, true ); } }
@grigasp said:
There's an option to tell the property grid to load properties of the related 3d element instead of the selected 2d one. Let me know if that works for you and you need guidance on how to set that up.
to which @simnorm replied:
I believe that Binh (@ezmobivietnam) had already tried that, but it would select the element in the Drawing model, not the element from the 3D model. Could you confirm Binh?
@ezmobivietnam the code you provided appears to implement your workaround. I am not interested in that - I want to see the code you used to try to "tell the property grid to load properties of the related 3d element instead of the selected 2d one".
@grigasp , Besides the workaround solution I shared above (using the selection set), I don't know that there is an option to tell the property grid to load properties of the related 3d element instead of the selected 2d one. Please teach me. Thanks!
The property grid uses presentation rules to load the properties. The default presentation rules used by the property grid tells it to load properties of selected element(s).
What you need is to supply an additional content rule that tells is to load related (3d) element properties when a 2d element is selected. The rule should use the ContentRelatedInstances specification and should either be specified before the default content rule in the rules list or have priority
attribute above 1000
.
Creating the ruleset could look like this:
import { Ruleset } from "@itwin/presentation-common";
import { DEFAULT_PROPERTY_GRID_RULESET } from "@itwin/presentation-components";
const myRuleset: Ruleset = {
...DEFAULT_PROPERTY_GRID_RULESET,
rules: [
{
ruleType: "Content",
condition: `SelectedNode.IsOfClass("2d_element_class_name", "2d_element_schema_name")`,
specifications: [{
specType: "ContentRelatedInstances",
relationshipPaths: [{
relationship: {
schemaName: "schema_name_of_relationship_between_2d_and_3d_elements",
className: "class_name_of_relationship_between_2d_and_3d_elements",
},
direction: "Forward", // or "Backward", depending on the relationship
}],
}],
},
...DEFAULT_PROPERTY_GRID_RULESET.rules,
],
}
The last puzzle piece is getting property grid to use those rules and it depends on what component you use to create the property grid:
PresentationPropertyDataProvider
directly, you can supply the ruleset through its constructor.@itwin/property-grid-react
package, PropertyGridUiItemsProvider
, that you're likely using to create the widget, takes PropertyGridProps
which contains a dataProvider
prop - you can create your own data provider with the custom ruleset as explained above.HTH
@grigasp , thanks for the details guidelines. Much appreciated! :-)
Hi @grigasp , we are using @itwin/property-grid-react
package, PropertyGridUiItemsProvider
, and PropertyGridProps
in our app.
Following your guideline, I was able to create a custom ruleset and it worked well. Thanks so much!
I am on the next step of making this custom ruleset work only on our Civil frontstage to avoid the impact on the existing functionalities of the app. Below are the steps I have taken:
PropertyGridRulesetModule
PropertyGridUiItemsProvider
, and change its default id
from PropertyGridUiItemsProvider
to PropertyGridRulesetUiItemsProvider
. Note: I did cheat the code to be able to change the value of the readonly
property id
.PropertyGridUiItemsProvider
, which uses the id PropertyGridRulesetUiItemsProvider
) for the Civil frontstage.And I got an issue:
The sheet viewer widget on the civil frontstage keeps using the default ruleset of the old PropertyGridUiItemsProvider, which uses the id PropertyGridUiItemsProvider
, for displaying data on the property grid and the new ruleset seems not be used.
I am not sure if the steps I did above (especially cheating the code in step 2) are correct or not. do you have any idea about it?
Thanks!
I'm not familiar with appui enough to guess why it might not work. Adding @GerardasB who may be able to help.
Create a new instance of PropertyGridUiItemsProvider, and change its default id from PropertyGridUiItemsProvider to PropertyGridRulesetUiItemsProvider. Note: I did cheat the code to be able to change the value of the readonly property id.
I don't think you need to do that. Instead, you can do this:
class MyUiItemsProvider implements UiItemsProvider {
public readonly id = "MyUiItemsProvider";
private _propertyGridProvider: PropertyGridUiItemsProvider;
constructor(props: PropertyGridUiItemsProviderProps = {}) {
this._propertyGridProvider = new PropertyGridUiItemsProvider(props);
}
public provideWidgets(stageId: string, stageUsage: string, location: StagePanelLocation, section?: StagePanelSection): ReadonlyArray<Widget> {
return this._propertyGridProvider.provideWidgets(stageId, stageUsage, location, section);
}
}
Hi @grigasp and @pmconne , since I have succeeded in applying a customized ruleset to the app following your guideline so I will close this ticket here. Thanks so much!
Binh
Describe the bug The EmphasizeElements APIs (override, isolate, hide, and emphasize) are not working on a sheet model but they work on the drawing model.
To Reproduce Steps to reproduce the behavior:
Expected behavior The selected elements on the sheet model should be emphasized/hidden/isolated/overridden.
Sandbox https://www.itwinjs.org/sandboxes/Thanh%20DinhDuong/Emphasize%20Elements%20-%202D%20Viewer%20Widget
Desktop (please complete the applicable information):