Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:

  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

Drive an Instantiator via an Enum input?

owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
Hi folks.

I'm writing a little FS that will make pockets in a target part for threaded "Heatserts" and bring in a part representing the insert.

Instead of building the parts within FS it imports a solid "Void" from and external file, transforms it into place and then boolean removes it from the target part.  Likewise for the insert itself.

File here:-
clicky



It's working nicely (thanks Neil) with the insert type hard coded into an Instantiator, so it'll put in an M6 insert no matter which option you chose!  (M6 was always my favourite "M" but it'd be nice to be able to use others!)

I added a choice of insert types via the enum at the top of the feature, but am unsure how to pass that value to the  Instantiator?

  //Set Which PartStudios to use for Instantiator based on user input
        if (definition.InsertTypeSelected == InsertType.M3x5_4x8)
        {
            debug(context, "M3 Selected");
            //Help!  I want to set a variable here so pick which import to use!
            
            
        }  
        
        if (definition.InsertTypeSelected == InsertType.M6x8_5x8)
        {
            debug(context, "M6 Selected");
        }  
        

I'd expect to be able to declare a variable, set that depending on the enum choice and use the variable in place of the "HeatsertVoidForM6x8_5mmx8mm::build" in this line of code:-
addInstance(instantiatorVoid, HeatsertVoidForM6x8_5mmx8mm::build, {  "transform" : toWorld(coordSystem(skPlane))} );

Help! 

Sorry for the newbie questions; it's like being a toddler again!

Cheers,
Owen S




  
Production Engineer
HWM-Water Ltd
Tagged:

Comments

  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    Ugly way for today:-
    for (var i = 0; i < TargetPointCount; i += 1)
                    {
                        debug(context,"LoopCounter:- " ~ i);
                        var skPlane = evOwnerSketchPlane(context, {
                            "entity" : TargetPoints[i]
                            
                            });
                            skPlane.origin = evVertexPoint(context, {
                                "vertex" : TargetPoints[i]
                            });
                     
                        var instantiatorVoid = newInstantiator(id + i + "instantiate");
                        
                         if (definition.InsertTypeSelected == InsertType.M3x5_4x8)
                            {
                                //debug(context, "M3 Selected");
                                //Help!  I want to set a variable here so pick which import to use!
                                addInstance(instantiatorVoid, HeatsertVoidForM3x5_4mmx8mm::build, {  "transform" : toWorld(coordSystem(skPlane))} );
                                
                            }  
                            
                            if (definition.InsertTypeSelected == InsertType.M6x8_5x8)
                            {
                                //debug(context, "M6 Selected");
                                addInstance(instantiatorVoid, HeatsertVoidForM6x8_5mmx8mm::build, {  "transform" : toWorld(coordSystem(skPlane))} );
                            }  
                    
                        
                    
                        instantiate(context, instantiatorVoid);
                        
                        //(3) Boolean remove Void from TargetPart
            
                        opBoolean(context, id + i + "boolean1", {
                        "tools" : qCreatedBy(id + i + "instantiate", EntityType.BODY),
                        "targets" : definition.TargetBody,
                        "operationType" : BooleanOperationType.SUBTRACTION
                        });  
                        
                        
                    //(4) Import HeatSert and //(5) Transfor Heatsert into place if checkbox is selected
                    if (definition.AddInsert==true)
                    {
                              
                        var instantiatorPart = newInstantiator(id + i + "instantiate2");
                        
                         if (definition.InsertTypeSelected == InsertType.M3x5_4x8)
                            {
                                //debug(context, "M3 Selected");
                                addInstance(instantiatorPart, HeatSert_M3x5_4mmx8mm::build, {  "transform" : toWorld(coordSystem(skPlane))} );
                                
                            }  
                            
                            if (definition.InsertTypeSelected == InsertType.M6x8_5x8)
                            {
                                //debug(context, "M6 Selected");
                                 addInstance(instantiatorPart, HeatSert_M6x5_8mmx8mm::build, { "transform" : toWorld(coordSystem(skPlane))} );
                            }  
                       
                        instantiate(context, instantiatorPart);
                        
                        //(6) Set some part properties. (Maybe!)
                        
                        
                    }
    There has to be a better way  :(
    Owen S
    Production Engineer
    HWM-Water Ltd
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 2,282
    You can set the configuration to use, like this:
    const boxInstance = addInstance(instantiator, BOX::build, { "configuration" : { "Length" : length, "Width" : width, "Height" : height, "Rotate" : rotate } });
    Neil Cooke, Director of Technical Marketing, Onshape Inc.
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 2,282
    You can get the enum value to drive the config, like this:
    export enum Sizes
    {
        annotation { "Name" : "M6" }
        M6,
        annotation { "Name" : "M8" } // my favourite
        M8
    }
    
    annotation { "Feature Type Name" : "My Feature" }
    export const myFeature = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            annotation { "Name" : "My Enum" }
            definition.size is Sizes;
        }
        {
                
            var config = toString(definition.size);
        }
    
    
    

    Neil Cooke, Director of Technical Marketing, Onshape Inc.
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    edited February 19

    Hi Neil,
    Thanks for the replies.  I may be missing the point.
    Are we talking cross purposes here, I need the instantiator to use a different "import" for each enum type?

    //Import all options
    
    //Insert M3 x 5.4mm Diameter x 8mm Length
    HeatSert_M3x5_4mmx8mm::import(path : "46a3854cbda96c62e0d2c699/74e51702442e9bb074c1f5f1/b169419f94a85683403aec80", version : "e52464d4091d572a1b9ff575");
    HeatsertVoidForM3x5_4mmx8mm::import(path : "46a3854cbda96c62e0d2c699/db1c68975d587fd3410ee360/0d1eec73a2af73cb44804e51", version : "9d14834abcda97000de0a1a7");
    
    //or
    
    //Insert M6 x 8.5mm Diameter x 8mm Length
    HeatSert_M6x5_8mmx8mm::import(path : "46a3854cbda96c62e0d2c699/62894ed0d7e00153dc3aa9b7/fd409ff7138ba0d1db28a644", version : "42da9a10f54abcc8248f75c4");
    HeatsertVoidForM6x8_5mmx8mm::import(path : "46a3854cbda96c62e0d2c699/62894ed0d7e00153dc3aa9b7/0d1eec73a2af73cb44804e51", version : "97487f7145d53c7631bb0c78");
    

    Pseudo code:-

     //Now decide which to PartStudios to use for Instantiator based on user input
    
    Var PartStudio_Void as partstudio
    Var PartStudio_Component as partstudio
    if (definition.InsertTypeSelected == InsertType.M3x5_4x8) { debug(context, "M3 Selected"); PartStudio_Void = HeatsertVoidForM3x5_4mmx8mm; //<< this is not correct
    PartStudio_Component = HeatsertVoidForM3x5_4mmx8mm; //<< this is not correct
    } if (definition.InsertTypeSelected == InsertType.M6x8_5x8) { debug(context, "M6 Selected"); PartStudio_Void = Different Part Studio
    } /// then later buried in the code inside a loop and never looked at again addInstance(instantiatorVoid, PartStudio_Void::build, { "transform" : toWorld(coordSystem(skPlane))} );
    // later still addInstance(instantiatorPart, PartStudio_Component::build, { "transform" : toWorld(coordSystem(skPlane))} );

    Is we can set a variable at the top of the code it's be much easier to maintain that sifting through the whole when new parts are added.

    If I'm making no sense don't be shy in telling me so!

    It's also Assembly Configs Webinar time so I think I'll leave this until the morning!
    Cheers, Owen S.
    Production Engineer
    HWM-Water Ltd
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 2,282
    No probs. I’m assuming you have configs in the instantiated docs rather than one part per doc?
    Neil Cooke, Director of Technical Marketing, Onshape Inc.
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    edited February 19
    Hi Neil, no configs in this version, just one part per part studio, modeled about the origin to make the transform simple :)
    Production Engineer
    HWM-Water Ltd
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 2,282
    In that case you need a namespace for each. USE CONFIGS!!!
    Neil Cooke, Director of Technical Marketing, Onshape Inc.
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    Yes!!  I hear you. :)   This feature isn't really for heatserts in the long term. I'm learning on this but it's really for electrical inputs for our data loggers, so each enum choice will be calling a totally different part, requiring a totally different hole.  (So a gland with multicore cable, or a 30-Way Mill-spec connector etc.)
    Production Engineer
    HWM-Water Ltd
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    edited February 19
    A bit like this:-
    Just set some sketch points on the blank back panel and use the FS to say "I want a usb here, an RJ45 here, a fan here" yada-yada..

    Oh, and then configure that. ;)
    O.S.
    Production Engineer
    HWM-Water Ltd
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 2,282
    edited February 20
    I thought this wouldn't work - I'm impressed that it does:
    CIRCLE::import(path : "b96ecf06f68f8a1ec70a1f3c", version : "a4d31802f9fe58b2f2e5d2fd");
    SQUARE::import(path : "4601f86b931b27691da4f558", version : "ffe1bfe7eadb35f07573ea5f");
    
    export enum ShapeType
    {
        annotation { "Name" : "Circle" }
        CIRCLE,
        annotation { "Name" : "Square" } 
        SQUARE
    }
    
    annotation { "Feature Type Name" : "Enum Test" }
    export const myFeature = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            annotation { "Name" : "Type" }
            definition.shape is ShapeType;
        }
        {
            var imports = {
                CIRCLE : CIRCLE::build,
                SQUARE : SQUARE::build
            };
    
            const instantiator = newInstantiator(id + "inst", {});
            const shapeInstance = addInstance(instantiator, imports[toString(definition.shape)], {});
            instantiate(context, instantiator);
        });
    You still have to import every Part Studio but it means the code is cleaner. 
    Neil Cooke, Director of Technical Marketing, Onshape Inc.
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    Neil, that's perfect, thanks for taking the time fella :+1: 
    I'll be giving that a try this afternoon.
    Thanks,
    Owen S
    Production Engineer
    HWM-Water Ltd
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 2,282
    No problem - you can also put the "imports" as a constant outside of the feature to make it easier to manage:
    CIRCLE::import(path : "b96ecf06f68f8a1ec70a1f3c", version : "a4d31802f9fe58b2f2e5d2fd");
    SQUARE::import(path : "4601f86b931b27691da4f558", version : "ffe1bfe7eadb35f07573ea5f");
    
    export enum ShapeType
    {
        annotation { "Name" : "Circle" }
        CIRCLE,
        annotation { "Name" : "Square" } 
        SQUARE
    }
    
    const imports = {
            CIRCLE : CIRCLE::build,
            SQUARE : SQUARE::build
        };
    
    annotation { "Feature Type Name" : "Enum Test" }
    export const myFeature = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            annotation { "Name" : "Type" }
            definition.shape is ShapeType;
        }
        {
            const instantiator = newInstantiator(id + "inst", {});
            const shapeInstance = addInstance(instantiator, imports[toString(definition.shape)], {});
            instantiate(context, instantiator);
        });

    Neil Cooke, Director of Technical Marketing, Onshape Inc.
  • MBartlett21MBartlett21 Member Posts: 1,581 EDU
    You could also use

    const imports = {
    ShapeType.CIRCLE : CIRCLE::build,
    ShapeType.SQUARE : SQUARE::build
    }; // Later... addInstance(instantiator, imports[definition.shape], {});
    MB - I make FeatureScripts: view FS (My FS's have "Official" beside them)
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    edited February 20
    Thanks folks, works perfectly :+1: exactly what I was after.
    I now have the begings of a bespoke standard parts library feature:-
    One further question.
    In the FS import, are resources being consumed as soon as the import is declared, or only if the feature uses that specific import?
    I'm concerned over bloat if I load this up with a big pile of options.  Would it be better to have separate features for different hardware types? 

    Cheers, Owen S.
    Production Engineer
    HWM-Water Ltd
  • lanalana Onshape Employees Posts: 468
    All the imported files with their dependencies are loaded into the process before the regeneration. However, don't let this consideration outweigh the usability of your custom feature. If loaded imports size become an issue, it'll be our task to manage the resources smarter. 
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    Thanks @lana, that's reassuring, if I'm being brutally honest I was concerned with Onshape's overheads, and my regen times. Not necessarily in that order...  ;) :p
    Production Engineer
    HWM-Water Ltd
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 927
    So in Neil's example, only one of CIRCLE and SQUARE would actually be regenerated (depending on the input), but the model definition for both would need some non-regen processing, slowing down some interaction.  While we could always do a better job managing resources, in Onshape as it is today, it's best to not have hundreds of imports.  Reference parameters are one technique for this, btw.
    Ilya Baran \ Director, Architecture and FeatureScript \ Onshape Inc
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    Thanks @ilya_baran that makes perfect sense.

    @NeilCooke I'm liking the Instantiate with configurations method.  I can't believe you didn't mention that!! (Kidding.)

    Getting ever closer to company specific configurable standard content:-

    Also as it's an import we get the explicit mate connectors and meta-data (supplier, PN, price, names etc) dropped in for no extra effort.

    Now I'm just waiting to get shouted at for instancing in a PartStudio :)
    Perhaps if the sketch point count is greater than one it'll have an option for any additional parts to set the exclude from BOM property, and set the appearance to a "dummy look", and then replicate just the first instance in the assembly.

    I'm having an unrelated issue but I'll post a separate topic if I'm still stuck tomorrow.

    Thanks for all your help folks :+1:
    Owen S
    Production Engineer
    HWM-Water Ltd
  • owen_sparksowen_sparks Member, Developers Posts: 2,292 PRO
    OK sussed the problem.  I was trying to configure the use of this feature in a PS and couldn't see how to get all the parameters with conditional visibility driven by a horizontal enum into a config table.

    So the goal here was a sort of "Super Derive" tool. 

    As good as the native feature is to my mind it has 3 drawbacks:-
    (a) You have to remember where you put your content and then point to it.
    (b) You're free to derive anything you like into a document.  I wanted to lock this down to a set of approved parts.
    (c) You can't configure a derive. (Well you can suppress it, but not configure what it brings into your document.)

    By the power of featurescript we have a single source, company wide standard content feature, that can be configured.




    Obviously this is intended for something a little more productive than bolts!  Target is an input field where a completed product is entered and the product builds itself.  Baby steps, but for today's effort I'm a happy CodeMonkey.

    Cheers,
    Owen S.
    Production Engineer
    HWM-Water Ltd
Sign In or Register to comment.