Skip to content

Conversation

@alfarok
Copy link
Contributor

@alfarok alfarok commented Aug 25, 2017

Purpose

QNTM-1284

The purpose of this PR is to enable the serialization and deserialization of Revit element selection nodes in Json. Previously Revit/Dynamo would freeze when attempting save a graph containing Revit selection nodes and the Json file is never written. The selection node should also maintain the Revit element id that is referenced so it will automatically be recognized when reopening a graph.

Supplemental to D4R PR #1768

giphy

Updated Json Output

{
  "Uuid": "ac033b17-4df4-4c56-bc42-533f7bad27fe",
  "IsCustomNode": false,
  "Description": null,
  "Name": "Home",
  "ElementResolver": {
    "ResolutionMap": {}
  },
  "Inputs": [],
  "Nodes": [
    {
      "ConcreteType": "Dynamo.Nodes.SelectFaces, DSRevitNodesUI",
      "NodeType": "ExtensionNode",
      "InstanceId": [
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:5:SURFACE",
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:6:SURFACE",
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:10:SURFACE",
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:18:SURFACE"
      ],
      "Id": "4d90c28040f247ef8cc0a3d0e6eed4d7",
      "Inputs": [],
      "Outputs": [
        {
          "Id": "4953c930ce1040ea828e6f8a94328d8a",
          "Name": "Surfaces",
          "Description": "The selected elements.",
          "Level": 2,
          "UseLevels": false,
          "KeepListStructure": false
        }
      ],
      "Replication": "Disabled"
    }
  ],
  "Connectors": [],
  "Dependencies": [],
  "Bindings": [],
  "View": {
    "Camera": {
      "Name": "Background Preview",
      "EyeX": -17.0,
      "EyeY": 24.0,
      "EyeZ": 50.0,
      "LookX": 12.0,
      "LookY": -13.0,
      "LookZ": -58.0,
      "UpX": 0.0,
      "UpY": 1.0,
      "UpZ": 0.0
    },
    "NodeViews": [
      {
        "ShowGeometry": true,
        "Name": "Select Faces",
        "Id": "4d90c28040f247ef8cc0a3d0e6eed4d7",
        "IsUpstreamVisible": true,
        "Excluded": false,
        "X": 135.60000000000002,
        "Y": 128.79999999999993
      }
    ],
    "Notes": [],
    "Annotations": [],
    "X": 0.0,
    "Y": 0.0,
    "Zoom": 1.0
  }
}

All RTF selection tests are passing including new tests:
rtf_tests_upload

Declarations

Check these if you believe they are true

  • The code base is in a better state after this PR
  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • All tests pass using the self-service CI.
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning, and are documented in the API Changes document.

Reviewers

@mjkkirschner
@QilongTang

FYIs

@jnealb
Copy link
Collaborator

jnealb commented Aug 25, 2017

@alfarok Is there a JIRA task for this?

/// <typeparam name="TSelection">The type which is used to constrain the selection.</typeparam>
/// <typeparam name="TResult">The type which is returned from the selection or subselection.</typeparam>
[DataContract]
public abstract class SelectionBase<TSelection, TResult> : NodeModel
Copy link
Contributor Author

@alfarok alfarok Aug 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only way I have been able to prevent the freezing from occurring, even when adding [JsonIgnore] on all public properties. The [DataContract] prevents serialization unless explicitly defined

Copy link
Collaborator

@radumg radumg Aug 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is the issue or not, but just in case it helps 😄 : where the deserialization is happening, have you tried specifying a JsonSerializerSettings settings object. This is where you declare how to handle nulls or missing properties during deserialization.
I've found explicitly declaring how to handle these clears up this kind of issues.

Also, I've had issues in the past with [JsonIgnore] being ignored itself, had to implement my own attribute.

IEnumerable<string> selectionIdentifier,
IEnumerable<PortModel> inPorts,
IEnumerable<PortModel> outPorts) : base(inPorts, outPorts)
{
Copy link
Contributor Author

@alfarok alfarok Aug 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also still getting double output ports when deserializing even after adding these parameters. I know this was due to recent changes in the node model base class but not sure why it is still occurring. Maybe an empty constructor should be created at the DSFaceSelection level

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah try that and make sure NodeModel(IEnumerable inPorts, IEnumerable outPorts) is called

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QilongTang @mjkkirschner I have actually made some progress by adding JsonConstructors through the entire inheritance chain shown in the description making sure to pass all the original parameters plus the revit element id propety data and port data. I am now getting a single output and the Revit referenced element is deserializing properly. The issue now is I can't select a new element after opening the file but I have a few ideas on resolving this.

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alfarok I believe the comment above is no longer valid? Do you have an update pic of the same DYN?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QilongTang yup this has all been resolved and I verified model elements outside of the standard geometry types are properly restoring as well (wall, roof, etc).
giphy

@alfarok
Copy link
Contributor Author

alfarok commented Aug 25, 2017

@jnealb yes QNTM-1284 adding it to the description

@alfarok
Copy link
Contributor Author

alfarok commented Aug 25, 2017

@mjkkirschner after updating all the references in D4R to point at my local build of Dynamo (opposed to the default NuGet packages) I still find that the base class I am referencing in Dynamo isn't updating in D4R. It seems it is still referencing some old cached metadata? For example, if I were to add a public property to the base class in Dynamo I am unable to access that inherited property in D4R

@mjkkirschner
Copy link
Member

mjkkirschner commented Aug 28, 2017

@alfarok please confirm your json constructor is called at all?

  • dump all the nuget packages for dynamo from the revit packages folder and save all your csproj files in dynamoRevit after they have been modified to point to your new dlls, not sure how you did this.
  • force a rebuild and clear all bin folders
  • If you replaced the dlls but did not change any references you might need to force them to repoint if version numbers changed or something like that.
  • try unloading all projects in the solution and forcing them to reload (right click project in solution explorer -> unload project, then -> reload project. See if this updates your referenced dll.
  • verify same build type (release v debug)

private List<TResult> selectionResults = new List<TResult>();
private List<TSelection> selection = new List<TSelection>();
private IEnumerable<string> selectionIdentifier;
private List<string> selectionIdentifier;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious why this needed to be a List?

{
selectionIdentifier = selection.Select(GetIdentifierFromModelObject).Where(x => x != null).ToList();
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small change is still needed here. I believe this logic prevents the selectionIdentifier from updating once an initial value is stored. It will appear as if the new selection has been updated in Dynamo background preview, however the initial selection id will serialize.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should write a test for that. Your own fault for bringing it up 😉

Copy link
Contributor Author

@alfarok alfarok Aug 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha probably for the best anyway...but does that mean RTF? 😕

ShouldDisplayPreviewCore = true;

SelectionIdentifier = selectionIdentifier;
ResetSelectionFromIds(SelectionIdentifier);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjkkirschner it could be an enum and this line changes to ResetSelectionFromIds(SelectionIdentifier.toList());

@alfarok alfarok changed the title [WIP] Revit element selection nodes should serialize and deserialize properly in Json Revit element selection nodes should serialize and deserialize properly in Json Aug 31, 2017
@alfarok alfarok added PTAL Please Take A Look 👀 and removed WIP labels Aug 31, 2017
@alfarok
Copy link
Contributor Author

alfarok commented Aug 31, 2017

Seems to be working as expected now, going to work on some testing to verify further

@alfarok
Copy link
Contributor Author

alfarok commented Sep 1, 2017

"Nodes": [
    {
      "ConcreteType": "Dynamo.Nodes.SelectFaces, DSRevitNodesUI",
      "NodeType": "ExtensionNode",
      "InstanceId": [
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:5:SURFACE",
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:6:SURFACE",
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:10:SURFACE",
        "3a376239-8db9-4f12-8dbb-774857dd156f-0000097b:18:SURFACE"
      ],
      "Id": "4d90c28040f247ef8cc0a3d0e6eed4d7",

@gregmarr Hey Greg, I was wondering if there should be another NodeType for SelectionNodes that select elements and return objects? Currently I am serializing as an ExtensionNode and adding a InstanceId property for Revit selection elements.

@gregmarr
Copy link
Contributor

gregmarr commented Sep 1, 2017

@gregmarr
Copy link
Contributor

gregmarr commented Sep 1, 2017

Does this node do anything else, or is it just a place to store these IDs?

@gregmarr
Copy link
Contributor

gregmarr commented Sep 1, 2017

Ah, this sounds like a geometry input node. We've talked about adding one but haven't yet. https://jira.autodesk.com/browse/AGD-47

Edit: Ah, yes, I see that you edited the original message to say that, I didn't see the update until after my first two responses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants