Advanced navigation inside GH canvas

Where can I see which functions (preferably IronPython/.net) drive the behavior of the JumpTo component:
2018-06-01%2012_17_49-Grasshopper%20-%20unnamed

Reason:
Following this thread https://discourse.mcneel.com/t/button-and-context-menu-options-on-component-through-ghpython/54638

What is the possibility to create an entry on the drop-down context menu that will jump to the connected input/output component.

This will be very useful when dealing with large GH scripts. Obviously users cannot put JumpTo component on every connection as it is now.

Thanks in advance.

You can use GH_NamedView.SetToViewport to adjust your canvas.

1 Like

:smiley: I don’t want to read the code or disassemble. I want to implement it with above mentioned method when right-clicking on an input or output.

Obviously to have this on each and every component would require David to do it (or whoever is responsible). But I could have it on my GHPython components.

Thanks for this:

But how can I find what the respective Input/Output is connected to?

See the documentation for GH_Component.Params

Params%20Property

Missing documentation :smiley:

Click GH_CompnentParamServer and navigate through the documentation (it’s fun to read that). In short, you need to process GH_Component.Params.Input/Output and retrieve positions from IGH_Param.Attributes.Bound

1 Like

Thanks for the info, I’ll have to spend some time to process :smiley:

Just in case you didn’t know, there are keyboard shortcuts to do something like this : Ctrl-Left and Ctrl-Right.

There’s also Attributes.Pivot for a single point of the GH_Param if you don’t need the full bounds

2 Likes

Once you have an IGH_Param object (which can be either a component input, a component output, or a free-floating object), you can iterate over its Sources. These are other IGH_Param objects that provide data to the original parameter.

Once you have a source, you can get its attributes, and then either use the Pivot, or the Bounds, or the OutputGrip of those attributes to find the location you want to look at. If you’re looking at Recipients instead of Sources, then you probably want to use the InputGrip point.

Here’s the code that Pancake used to pick connected docobjects with some hashing

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Grasshopper.Kernel;

namespace ghManager.GH.Tweaks
{
    class GhStream
    {
        public static List<IGH_ActiveObject> GetConnectedObjects(ICollection<IGH_ActiveObject> sourceObjs, bool upstream, bool downstream)
        {
            var objs = new List<IGH_ActiveObject>();
            var objsGuid = new HashSet<Guid>();

            GetConnectedObjectsRecursive(sourceObjs, upstream, downstream, objsGuid, objs);

            return objs;
        }

        private static void DealWithParamList(List<IGH_Param> paramList, List<IGH_ActiveObject> streamObjs, HashSet<Guid> guids, HashSet<Guid> globalGuids)
        {
            foreach (var param in paramList)
            {
                if (param.Kind == GH_ParamKind.unknown)
                    continue;

                var docObj = param.Kind == GH_ParamKind.floating ? param : param.Attributes.GetTopLevel.DocObject;
                if (docObj is IGH_ActiveObject && !guids.Contains(docObj.InstanceGuid) && !globalGuids.Contains(docObj.InstanceGuid))
                {
                    streamObjs.Add(docObj as IGH_ActiveObject);
                    guids.Add(docObj.InstanceGuid);
                }
            }
        }

        private static void GetConnectedObjectsRecursive(ICollection<IGH_ActiveObject> sourceObjs,
            bool upstream, bool downstream, HashSet<Guid> objsGuid, List<IGH_ActiveObject> objs)
        {
            var instream = new List<IGH_ActiveObject>();
            var instreamGuid = new HashSet<Guid>();

            foreach (var obj in sourceObjs)
            {
                var guid = obj.InstanceGuid;
                if (objsGuid.Contains(guid))
                    continue;
                objsGuid.Add(guid);

                List<IGH_Param> upstreamParams = null;
                List<IGH_Param> downstreamParams = null;
                switch (obj)
                {
                    case IGH_Param objParam:
                        if(upstream)
                            upstreamParams = new List<IGH_Param>(objParam.Sources);
                        if(downstream)
                            downstreamParams = new List<IGH_Param>(objParam.Recipients);
                        break;
                    case IGH_Component objComponent:
                        if (upstream)
                        {
                            upstreamParams = new List<IGH_Param>();
                            foreach (var input in objComponent.Params.Input)
                                upstreamParams.AddRange(input.Sources);
                        }

                        if (downstream)
                        {
                            downstreamParams = new List<IGH_Param>();
                            foreach (var output in objComponent.Params.Output)
                                downstreamParams.AddRange(output.Recipients);
                        }
                        
                        break;
                    default:
                        continue;
                }

                if (upstream)
                    DealWithParamList(upstreamParams, instream, instreamGuid, objsGuid);
                if (downstream)
                    DealWithParamList(downstreamParams, instream, instreamGuid, objsGuid);
            }

            if (instream.Count > 0)
            {
                GetConnectedObjectsRecursive(instream, upstream, downstream, objsGuid, objs);
                objs.AddRange(instream);
            }
        }
    }
}
1 Like

Thanks for sharing @gankeyu