Progress on ParaView widgets

Hi all (esp. @Bob_Obara) ,

There’s a lot left to do (see below), but here’s some progress on getting ParaView widgets adapted to SMTK’s qtItem class so 3-d widgets can edit attribute item values.

What’s Left

  • Need to generalize to widgets other than the box widget.
  • Need to connect signals and slots so widget and attribute-item are connected.
    • Also, initialization should be supported so that default values in the attribute (which may not make sense for the modeling workflow) are not always preferred over sizing related to the scene bounds in ParaView. (see post below for some ideas)
  • Determine how much control applications/workflows should be given over the Qt widget appearance. For example, should the Rotation checkbox in the screenshot be permanently disabled in some workflows? How can this be done in the ParaView widget?
  • The widget representation is tied to the active view (the one active at the time the qtUIManager is created by the attribute panel)… we should probably add signals so that when the active view changes the widget moves to that view (assuming it is capable of showing the widget) or disable (if it cannot show the widget, e.g., the spreadsheet view). (SMTK MR 1421)
  • Verify that load/save state do not attempt to serialize/deserialize the widget (or fix it so they don’t) as the widget will be recreated by the attribute panel upon demand.
  • Figure out better, more usable interaction for enabling/disabling the widget (other than the “Show Box” checkbox in the attribute panel).

This is now in SMTK merge request 1252 and provides some more functionality than the above (more widgets than just the box). There is still a lot left to do, but probably the biggest blocker is providing bounds to some of the widgets (the plane and box in particular) based on datasets that have been loaded.

Also, here’s some more eye candy that shows off spline editing:

Finally, here’s the SMTK sbi file I use to demo the widgets.

<?xml version="1.0" encoding="utf-8" ?>
<SMTK_AttributeResource Version="3">
  <Definitions>
    <AttDef Type="Material">
      <AssociationsDef Name="Material Blocks" NumberOfRequiredValues="0" Extensible="true">
        <MembershipMask>face</MembershipMask>
      </AssociationsDef>
      <ItemDefinitions>
        <Component Name="Entities" NumberOfRequiredValues="0" Extensible="true"
                   MaxNumberOfValues="1" Optional="true" IsEnabledByDefault="false">
          <Accepts>
            <Resource Name="model" Filter="volume|face"/>
          </Accepts>
        </Component>
        <Double Name="Density">
          <RangeInfo>
            <Min Inclusive="false">0.0</Min>
          </RangeInfo>
        </Double>
        <Double Name="Viscosity">
          <RangeInfo>
            <Min Inclusive="false">0.0</Min>
          </RangeInfo>
        </Double>
        <Double Name="bbox" NumberOfRequiredValues="6" Optional="true">
        </Double>
        <Group Name="plane" NumberOfRequiredGroups="1" Optional="true">
          <ItemDefinitions>
            <Double Name="feble" NumberOfRequiredValues="3">
              <DefaultValue>1.0,0.0,0.0</DefaultValue>
            </Double>
            <Double Name="pluft" NumberOfRequiredValues="3">
              <DefaultValue>0.0,0.0,0.0</DefaultValue>
            </Double>
          </ItemDefinitions>
        </Group>
        <Group Name="ball" NumberOfRequiredGroups="1" Optional="true">
          <ItemDefinitions>
            <Double Name="plorm" NumberOfRequiredValues="1">
              <DefaultValue>1.0</DefaultValue>
            </Double>
            <Double Name="trub" NumberOfRequiredValues="3">
              <DefaultValue>0.0,0.0,0.0</DefaultValue>
            </Double>
          </ItemDefinitions>
        </Group>
        <Group Name="squiggle" NumberOfRequiredGroups="1" Optional="true">
          <ItemDefinitions>
            <Void Name="nuftly"/>
            <Double Name="xyzzyx" NumberOfRequiredValues="0" Extensible="true"/>
          </ItemDefinitions>
        </Group>
        <Group Name="cornulature" NumberOfRequiredGroups="1" Optional="true">
          <ItemDefinitions>
            <Void Name="nuftly"/>
            <Double Name="xyzzyx" NumberOfRequiredValues="0" Extensible="true"/>
          </ItemDefinitions>
        </Group>
      </ItemDefinitions>
    </AttDef>
    <AttDef Type="BoundaryCondition">
      <AssociationsDef Name="BC Sets" NumberOfRequiredValues="0" Extensible="true">
        <MembershipMask>edge</MembershipMask>
      </AssociationsDef>
    </AttDef>
    <AttDef Type="Velocity" BaseType="BoundaryCondition">
      <ItemDefinitions>
        <Double Name="Velocity" NumberOfRequiredValues="2"></Double>
      </ItemDefinitions>
    </AttDef>
    <AttDef Type="Pressure" BaseType="BoundaryCondition">
      <ItemDefinitions>
        <Double Name="Pressure"></Double>
      </ItemDefinitions>
    </AttDef>
  </Definitions>
  <Attributes>
    <Att Name="Air" Type="Material">
      <Items>
        <Component Name="Entities" NumberOfValues="0"></Component>
        <Double Name="Density"><Values><Val Ith="0">1.0</Val></Values></Double>
        <Double Name="Viscosity"><Values><Val Ith="0">0.000001</Val></Values></Double>
        <Double Name="bbox">
          <Values>
            <Val Ith="0">0.0</Val>
            <Val Ith="1">0.05</Val>
            <Val Ith="2">0.0</Val>
            <Val Ith="3">0.05</Val>
            <Val Ith="4">0.0</Val>
            <Val Ith="5">0.125</Val>
          </Values>
        </Double>
        <Group Name="plane" Enabled="true">
          <GroupClusters>
            <Cluster Ith="0">
              <Double Name="feble">
                <Values>
                  <Val Ith="0">0.0</Val>
                  <Val Ith="1">0.0</Val>
                  <Val Ith="2">1.0</Val>
                </Values>
              </Double>
              <Double Name="pluft">
                <Values>
                  <Val Ith="0">0.025</Val>
                  <Val Ith="1">0.025</Val>
                  <Val Ith="2">0.0</Val>
                </Values>
              </Double>
            </Cluster>
          </GroupClusters>
        </Group>
        <Group Name="ball" Enabled="true">
          <GroupClusters>
            <Cluster Ith="0">
              <Double Name="plorm">
                <Values>
                  <Val Ith="0">0.0875</Val>
                </Values>
              </Double>
              <Double Name="trub">
                <Values>
                  <Val Ith="0">0.0</Val>
                  <Val Ith="1">0.0</Val>
                  <Val Ith="2">0.0625</Val>
                </Values>
              </Double>
            </Cluster>
          </GroupClusters>
        </Group>
        <Group Name="squiggle" Enabled="true">
          <GroupClusters>
            <Cluster Ith="0">
              <Void Name="nuftly" Enabled="false"/>
              <Double Name="xyzzyx" NumberOfValues="12">
                <Values>
                  <Val  Ith="0">0.0</Val><Val  Ith="1">0.0</Val><Val  Ith="2">0.0</Val>
                  <Val  Ith="3">1.0</Val><Val  Ith="4">0.0</Val><Val  Ith="5">0.0</Val>
                  <Val  Ith="6">1.0</Val><Val  Ith="7">1.0</Val><Val  Ith="8">0.0</Val>
                  <Val  Ith="9">0.0</Val><Val Ith="10">1.0</Val><Val Ith="11">0.0</Val>
                </Values>
              </Double>
            </Cluster>
          </GroupClusters>
        </Group>
        <Group Name="cornulature" Enabled="false">
          <GroupClusters>
            <Cluster Ith="0">
              <Void Name="nuftly" Enabled="false"/>
              <Double Name="xyzzyx" NumberOfValues="12">
                <Values>
                  <Val  Ith="0">0.0</Val><Val  Ith="1">0.0</Val><Val  Ith="2">0.0</Val>
                  <Val  Ith="3">1.0</Val><Val  Ith="4">0.0</Val><Val  Ith="5">0.0</Val>
                  <Val  Ith="6">1.0</Val><Val  Ith="7">1.0</Val><Val  Ith="8">0.0</Val>
                  <Val  Ith="9">0.0</Val><Val Ith="10">1.0</Val><Val Ith="11">0.0</Val>
                </Values>
              </Double>
            </Cluster>
          </GroupClusters>
        </Group>
      </Items>
    </Att>
  </Attributes>
  <Views>
    <View Type="Group" Title="Bar" TopLevel="true">
      <Views>
        <View Title="Material"/>
      </Views>
    </View>
    <View Type="Instanced" Title="Material">
      <InstancedAttributes>
        <Att Type="Material" Name="Air">
          <ItemViews>
            <View Item="bbox" Type="Box"/>
            <View Item="plane" Type="Plane" Origin="pluft" Normal="feble"/>
            <View Item="ball" Type="Sphere" Center="trub" Radius="plorm"/>
            <View Item="squiggle" Type="Spline" Points="xyzzyx" Closed="nuftly" Color="0 1 0"/>
            <View Item="cornulature" Type="Spline" Polyline="true" Points="xyzzyx" Closed="nuftly"/>
          </ItemViews>
        </Att>
      </InstancedAttributes>
    </View>
  </Views>
</SMTK_AttributeResource>

After some discussion, we are going to start by adding some configuration XML to the item’s view that specifies how and when the widgets should be initialized with item values and vice-versa.

Some ideas on the conditions that affect which side (the widget or the SMTK attribute’s item) should “win” control are

  • initialization state: whether the item’s value is the default value (or if the item has no default, whether the value is set or not); if the item is uninitialized, then geometric data in SMTK may be used to place the widget.
  • fallback strategy: if the item is uninitialized and there is no geometry (as defined below) available, then a FallbackStrategy tag-attribute specifies the widget’s behavior:
    • Hide the widget so that its lack of default placement does not cause confusion; or
    • Force causes the widget to be shown and its placement determined using the item’s default values.
  • geometry source: what value the XML configuration for the item’s view specifies for the WidgetPlacement tag-attribute:
    • Item: the item should always be used to initialize the widget’s placement in the rendered scene. The fallback strategy is ignored in this case.
    • Associations: when the item is uninitialized and its parent SMTK attribute has model or mesh components associated with it, those components should be used to initialize the widget’s placement. If there are no relevant associated components, then the fallback strategy is used (e.g., the widget visibility will be turned off).
    • Links: when the item is uninitialized, the bounds of all model/mesh resources that share a link to the item’s attribute’s resource will be used to initialize the widget’s placement. If there are no relevant linked resources, then the fallback strategy is used.
    • Scene: when the item is uninitialized, use any model or mesh resources currently loaded to initialize the widget’s placement. If no relevant resources are loaded, then the fallback strategy is used.
    • BestGuess: when the item is uninitialized, use the associated components as Associations does above. If there are no associated components, then fall back to linked resources as Links does above. If there are no linked resources, fall back to any loaded resources as Scene does above. Finally, if there is no recourse, the fallback strategy is used.
  • updates: whether the placement should be updated as conditions change. For example, if the widget is hidden because there are no associated model entities and the user afterwards adds some associations, should the widget immediately be shown? Or should the user be required to manually click the widget’s “Show” checkbox? Should changes to values outside the item (linked resources, associated components) force the widget placement to be reset? Even after interaction has occurred?

The use cases we considered were:

  • The workflow wants to provide a way to transform a model component using a box widget. The model component should always be associated to the attribute holding the transform parameters. The transform parameters are represented using a box widget. In this case, the box widget should never be shown until an association exists, so
    <ItemViews>
      <View Item="transform" Type="Box"
        WidgetPlacement="Associations" FallbackStrategy="Hide"/>
    </ItemViews>
    
  • The workflow wants the user to choose a plane to which auxiliary geometry will be snapped. In this case, we could use either Links or Scene to place the plane depending on whether we expect multiple model resources to be loaded and whether the attribute will have links to just a subset or not.
    <ItemViews>
      <View Item="snap plane" Type="Plane"
        WidgetPlacement="Scene" FallbackStrategy="Hide"/>
    </ItemViews>
    

@Bob_Obara & @tj.corona Any thoughts on the above? It is mostly what we talked about. I would not implement anything related to updates initially.

@chart3388 The point and line widgets are now in master, albeit without the widget placement support yet. However, you should now be able to use ParaView widgets for points and lines as below.

<?xml version="1.0" encoding="utf-8" ?>
<SMTK_AttributeResource Version="3">
  <Definitions>
    <AttDef Type="Material">
      <ItemDefinitions>
        <Double Name="handle" NumberOfRequiredValues="3" Optional="true"/>
        <Group Name="segment" NumberOfRequiredGroups="1" Optional="true">
          <ItemDefinitions>
            <Double Name="gnorp" NumberOfRequiredValues="3">
              <DefaultValue>1.0,0.0,0.0</DefaultValue>
            </Double>
            <Double Name="yuptl" NumberOfRequiredValues="3">
              <DefaultValue>0.0,1.0,0.0</DefaultValue>
            </Double>
          </ItemDefinitions>
        </Group>
      </ItemDefinitions>
    </AttDef>
  <Attributes>
    <Att Name="Croftl" Type="Material">
      <Items>
        <Double Name="handle">
          <Values>
            <Val Ith="0">0.035</Val>
            <Val Ith="1">0.035</Val>
            <Val Ith="2">0.125</Val>
          </Values>
        </Double>
        <Group Name="segment" Enabled="true">
          <GroupClusters>
            <Cluster Ith="0">
              <Double Name="gnorp">
                <Values>
                  <Val Ith="0">0.0</Val>
                  <Val Ith="1">0.0</Val>
                  <Val Ith="2">1.0</Val>
                </Values>
              </Double>
              <Double Name="yuptl">
                <Values>
                  <Val Ith="0">0.025</Val>
                  <Val Ith="1">0.025</Val>
                  <Val Ith="2">0.0</Val>
                </Values>
              </Double>
            </Cluster>
          </GroupClusters>
        </Group>
      </Items>
    </Att>
  </Attributes>
  <Views>
    <View Type="Group" Title="Bar" TopLevel="true">
      <Views>
        <View Title="Material"/>
      </Views>
    </View>
    <View Type="Instanced" Title="Material">
      <InstancedAttributes>
        <Att Type="Material" Name="Croftl">
          <ItemViews>
            <View Item="handle" Type="Point"/>
            <View Item="segment" Type="Line" Point1="gnorp" Point2="yuptl"/>
          </ItemViews>
        </Att>
      </InstancedAttributes>
    </View>
  </Views>
</SMTK_AttributeResource>