Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UFlowGraphNode::ReconstructNode and associated functions rewrite to clean up graph behavior #264

Open
wants to merge 3 commits into
base: 5.x
Choose a base branch
from

Conversation

HomerJohnston
Copy link
Contributor

  • Removed some duplicate calls to reconstruct nodes; ReconstructNode() would frequently run 2 or 3 times before, usually only runs once now
  • Added additional flags to skip ReconstructNode(): no longer reconstructs before saving the graph, no longer reconstructs a node before deleting the node
  • ReconstructNode() completely rewritten to clean up logic and resolve bugs with 'false' graph asset dirtying or missed pin change updates
  • UFlowGraphNode::RefreshContextPins() function completely replaced by two new substantial functions:
    • TryUpdateAutoDataPins()
    • TryUpdateNodePins()

1) Make all pin types and sources correctly update when modified, 2) fix unnecessary dirtying of flow asset upon opening (unnecessary Modify() calls)
- Added UFlowGraph "IsSaving" state; made UFlowGraphNode skip node reconstruction during save
- Added UFlowGraphNode "IsDestroyingNode" state, made UFlowGraphNode skip node reconstruction during node deletion
- Fixed minor bug from previous commit which broke certain transaction undos in ReconstructNode()
@@ -93,16 +93,9 @@ void UFlowGraph::RefreshGraph()
}
}

// This function will (eventually) result in all graph nodes being reconstructed
UnlockUpdates();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is better to remove UpdateAsset() call from UnlockUpdated(), because it's unclear that this function does this (unless you specifically look into the function body) and add it instead of deleted code below.
And actually instead of having two functions just to change one bool value I would write TGuardValue<uint32> LockUpdatesGuard(bLockUpdates, true); at the beginning of the corresponding block (or even simpler bLockUpdates = true/false). Or provide a better name for UnlockUpdates(), for example, UnlockUpdatesAndUpdateAsset() (too mouthful and clearly states two separate responsibilities of this function).

Copy link
Contributor Author

@HomerJohnston HomerJohnston Feb 16, 2025

Choose a reason for hiding this comment

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

I very much agree in principle! However, the UnlockUpdates() code basically connects directly into the new "Addons" code, and I haven't studied the addons code at all yet (I don't use any addons). So I think this topic might make a good future PR for further cleanup, but I'm not sure if I want to risk expanding this PR into it. It would take me a while to make sure I'm comfortable with it (might not have more free time for a few weeks).

(PS - thanks for the review!)

// Corrupt? This should never happen
if (!IsValid(NodeInstance))
{
UE_LOG(LogFlow, Error, TEXT("FlowGraphNode has no NodeInstance, graph may be corrupt!"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add more info about the node being corrupt and also add ensureMsgf(Always)?

{
if (UFlowAsset* FlowAsset = NodeInstance->GetFlowAsset())
Modify();
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this call be before TryUpdateAutoDataPins()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not necessary because the flow graph node isn't modified until this point (and it doesn't really matter when exactly you call Modify, as long as it gets called sometime during the process), but!! You made me realize I should have called Modify() on the FlowNode, elsewhere in my new functions. Thanks :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I missed that pins are being changed in FlowNodeInstance and not in the UFlowGraphNode, but yeah, I meant that)

for (const FFlowPin& Left : LeftPins)
{
// For each required pin, make sure the existing pins array contains a pin that matches by name and type
if (!RightPins.ContainsByPredicate( [&Left] (const FFlowPin& Right)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would move lambda out of if statement - easier to read.

- Added 2 missing FlowNode Modify() calls
- Replaced logs with ensures
- Cleanup Lambda
@MothDoctor MothDoctor self-assigned this Feb 19, 2025
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.

3 participants