Wish: Change wire style of the whole component

Possibility to change the wire type of all inputs of a component simultaneously. Additional option when right-clicking on the component to have that available, and not only when clicking on a particular input.

I want to get rid of those options altogether, let alone make it easier to assign them en masse…

Are you switching wires to hidden to reduce the visual clutter of a file?

Why would you want to get ride of them completely they are so useful?

Saying that i mainly use them on parameter components where i want a faint wire to go from an input to a set of switches etc somewhere further down the code.

How about just remove the wire option from main components but leave them available in the parameter (Geometry, Primitive, etc) components only.

Are they useful? They obfuscate the logic of the file. Seems to me they solve problems which shouldn’t be there to begin with.

Ideally you’d be able to reference an input variable directly by name rather than having a physical wire. If there’s a slider which set the thickness of the sheet material you’re using for a specific assembly, and that thickness appear everywhere because you always have to subtract it or add it to values, then I’d much rather the slider is marked as a global object and then you’d be able to use the {thickness} value everywhere. Even inside expressions, so you can extrude a shape with a specific height and put the expression x - {thickness} in the height input.

1 Like

Not only that, I’m getting a serious drop in frame rate when there are over a hundred wires flying around. GH is stuttering while panning without anything self-updating turned on.

Note: I have i74770 K and GTX1060.

Can you show a spoiler screenshot of your idea?
I’m glad a global component will be introduced. Perhaps this is how it should be. Rendering of wires will also be avoided.

Could this also give the possibility of avoiding recursive errors without using sticky?

Quick mock up, I haven’t thought much about how exactly values would be marked as global, or even whether it’s possible for all parameters, or only those carrying single values, or only specific objects.

The expression api in GH2 does already have support for global values including inheritance, so if a global is used inside an expression, the object which owns that expression will be updated when the global changes.

2 Likes

I wonder:

  • Upon update how would you differentiate the globals from the other components to avoid “gloabl not set” errors?

  • When using globals as input for scripting components have you thought of a way to create immutable inputs for globals?

  • Will there be a dropdown list of all globals for users to pick from?

  • How will they be called (and differentiated) inside the code is also another interesting thing. You should reserve the name somehow to not change it from inside the code.

If any object references a global which is not available, I guess it basically amounts to the same as a faulty data conversion. You get an error message and probably a null value instead.

The inputs of scripting components are the same as the inputs for any other component. So if you reference a global integer from a scripting input, you just see that integer inside the script. If you want to access globals as delegates from within a C# or Python script, then some other approach is needed and I haven’t thought about that yet.

These are UI details, I haven’t gotten to that stage at all yet.

Assuming by “code” you are referring to expressions, at the moment any undeclared variable inside an expression is assumed to represent a global read operation. When I compile the expression code I replace undeclared variables with method invokes. So for example if you have the parameter expression:

double x2 = x * x;
return (x2 - 0.5 * x2) + name;

then it will get wrapped inside a method signature first so the x variable becomes available:

dynamic Run(dynamic x)
{
  double x2 = x * x;
  return (x2 - 0.5 * x2) + name;
}

And then it is tokenised and if there’s any dangling symbols they are replaced by a method node, giving us:

dynamic Run(dynamic x)
{
  double x2 = x * x;
  return (x2 - 0.5 * x2) + TryFindGlobal("name", thisCanvasObject);
}

This will compile into a valid .NET assembly and inside the TryFindGlobal() method I go and traverse the document looking for a global called "name". If I find such a value I return it and add the thisCanvasObject to the list of recipients of the global provider, otherwise there’s an exception which informs the user that name is neither a declared variable nor a known global.

Thanks for the insight David.

I meant code from scripting component. If you define a variable which name conflicts with one of the globals. Like when using lambda, try, def, elif, break, etc. in python. A kind of reserved name which you cannot use in the script. That could be a way to call globals inside scripting components though I’ve no idea how could this be implemented since usually reserved names are compiled to DLLs and not dynamically set. Perhaps this could also be implemented using a module like rhinoscriptcontext in Python. I guess that’s for Giulio and Steve to figure it out.

  • Will globals have a container component dedicated for them? Some sort of dictionary (like sticky) This is why I asked:

If globals are created using a dedicated component, like for example:
image

this component will have to be updated first when the new calculation cycle begins or they should be excluded from the calculations and in another thread/process.

Perhaps persistent gloabals could allso be useful. Accessing them from whatever .GH is opened this will allow you to keep the same naming for all definitions.

WoW this is so vast, so many ideas come to my mind :slight_smile:

that is why he says he wants to use delegates or similar. This is exactly the right direction to go.
C# doesn’t support the concept of true global variables. You can like or not, and sometimes it would be good to have one. But globals are dangerous for exactly the reason you pointed out: naming collisions. Especially on plugin base, since people don’t know the full code on runtime. So instead of using strings as identifier you are using the address. If the delegate (== method pointer) is null, it uses the default value (and maybe throws a warning). Its a simple, fast and safe approach.

Furthermore this is a problem you cannot solve from a scripting perspective.

I believe Davids proposal is a very good way to reduce wire usage and making a definition more persistent. I don’t know why you encounter frame drops, my laptop has much lower specs, but why no reducing wire/component count by using the “traditional” approaches: cluster or scripts, expression components. I’ve no idea what kind of gh definitions you are creating, but my work-related definitions contains between 2-4 of such global settings, which is easy to handle.
Furthermore if you subdivide your scripts into medium-sized-code blocks you not only improve the overview, you can also much easier comment and handle exceptions/special cases. Visual/Node-based programming is always a compromise of simplicity against complexity.

Hmm, well he speaks csharp, I can only say “Hello, world!” in this languge. :smile:

Scipts I use a lot, I cannot crete clusters in the early stage of my definitions because I have a lot of changes still happening.

I hope I understand correctly. I’ve made a few tests that using Expression Component uses more processing tine than ghpython for example. Could you show an example of what you mean? Perhaps, you mean entering expressions for the inputs. In which case my answer is, yes. I use expressions but in early stage I need to identify potential problems visually so I use a lot of panels and arithmetic components. In later stage I replace them with expressions.

Drops appear when I have hundreds ofNormal (display type) wires stretching at long distances. When they are thin and invisible I have no such problems.

In addition to naming conflicts and compilability, the other main reason for not using named statics is the source/recipient relationship. If your script (be it python or C# or VB) uses a global, it needs to be expired when that global changes value. I have no way of finding out if a script reads some value, it’s only when it goes through a method invoke that I can get into the middle of it and build the expiration lists.

well if its about reducing components/wires, the expression component can be quite powerful, at least in terms of vector algebra:


expressionExample.gh (11.8 KB)

1 Like

this would be the same without expression component

Thanks for the clarification Tom, have in mind this component is heavier (processing-wise) than using ghpython. :wink:

seriously, who cares? For someone not knowing how to code this is super simple way in reducing the component/wire count. As said, visual programming is mainly for people being no programmers. This is a compromise. Its very hard to create performant code with connecting precompiled components together.
Furthermore, one aspect of writing efficent code is, that you know at which places it makes sense to optimise. Vector math is super fast, even if you do this 1000 times the benefit of a low level implementation is low. Furthermore, lets assume your definition prevents you in drawing 1000 curves. Even if its super slow and needs 1 hour of computation, it will still be better as manually drawing 1000 curves.

Edit: I do like optimising code, but the amount of time I’ve spend into this is not economic, but rather a hobby :slight_smile:

Not arguing with that, I said it as FYI.

I agree, nearly impossible. You know I thought about it, perhaps it would benefit a lot if all components were in a way scripting components, to modify on the fly. Double click and you see what the code is behind them. Some kind of option in the GH preferences to toggle between scripting and normal, depending on the level of coding of the user. Advanced ones with some coding experience could benefit much. Those who don’t have any experience could leave them (as if compiled) and use them with their general functionality.

I’m not familiar with dynamo but I saw videos and it seems exactly like that.
EDIT: I guess I was wrong about that.

yes, this is what dynamo does (partially), its called “node-to-code”. Blender has also a similar feature. You can select a command and paste it as code. If every Rhino-Command would be callable by script like this… :dream:

1 Like

This is because expressions are parsed by a rather naive finite state machine I adapted for GH1. In GH2 all expressions will be compiled into .NET assemblies (slightly bigger cost up front) and will thus run at the same speed as any other .NET code.

2 Likes