Window Crafter: Free SketchUp Plugin Looking for Testers

Point 1: Cuts Opening - Cutting components need to be modeled lying down on the ground plane. The ground plane is the cutting plane, so if you set the definition’s behavior to cuts_opening then the maximum bounds of the component’s geometry that cross the XY plane, will be the opening cut into the face when placed. (The component must be inserted into the same context as the face surface. Cutting components cannot currently cut through solids, but there are other extensions that do this.)

Then as asked in point 2 for gluing, you also set the behavior of snapto depending upon what orientation of surface the component should glue to. For vertical walls, set doors and normal windows to SnapTo_Vertical. For sky light type windows likely set this to SnapTo_Sloped, etc.

SketchUp Ruby API Documentation

I’ll look into making the wall cut automatically when a window or door is added.

Changing an existing door or handle to a completely different model is a bit tricky. I tried it before, but the handles ended up in the wrong positions, so that feature is a little beyond my abilities at the moment.

Right now, the plugin lets you choose between different door styles and handles. If there is a specific door you would like me to add, let me know. You can send me the design or the Ruby code.

so, i’ve been using my trainees of the week as guineapigs.

They love the tool.
2 main things : it’s not in french. I mean, it’s still an early version, and still, they managed to make a couple doors / windows.

and when putting dimensions, it needs to respect the dot / comma separator.
here in france we use a decimal comma, but the plugin uses a decimal dot.

but other than that, they love it.


oh yeah also.

over here, windows come with 2 panels.
we’re limited to one… unless we want our windows to chop some heads I guess :slight_smile:

@Hamzah198501 See Sketchup::RegionalSettings

Wow.. din’t know about this.
In my tools I’m accepting both formats, nomatterwhat :sweat_smile:

For this type, you can try using the French doors option, since it allows two panels. But yes, I should add the same option for windows as well.

Noted.

Try this version

window_crafter_v1.4.0.rbz (123.6 KB)

Just to follow-up on RuboCop:

9 files inspected, 2236 offenses detected, 2051 offenses autocorrectable

This might work for you as a starter file:

Save as .rubocop.yml
# Formatting might be finicky when pasted. place in extension folder.

# For Power Shell
# cd "C:\Users\WHEREITIS\window_crafter_v1.4.0"
# rubocop --plugin rubocop-sketchup

plugins:
  - rubocop-sketchup

AllCops:
  TargetRubyVersion: 3.2
  DisabledByDefault: false
  DisplayStyleGuide: true
  NewCops: disable

  SketchUp:
    SourcePath: .
    EncryptedExtension: true
    TargetSketchUpVersion: 2025

SketchupDeprecations:
  Enabled: true
SketchupPerformance:
  Enabled: true
SketchupRequirements:
  Enabled: true
SketchupSuggestions:
  Enabled: true
SketchupBugs:
  Enabled: false

# Disable unstable cops
SketchupBugs/MaterialName:
  Enabled: false
SketchupBugs/RenderMode:
  Enabled: false
SketchupBugs/UniformScaling:
  Enabled: false

# Disable stricter structural cops
SketchupRequirements/FileStructure:
  Enabled: false
SketchupRequirements/SketchupRequire:
  Enabled: true
SketchupRequirements/SketchupExtension:
  Enabled: false
SketchupSuggestions/Compatibility:
  Enabled: true
Layout/EndOfLine:
  Enabled: true
Layout/LineLength:
  Enabled: false
Style/StringLiterals:
  Enabled: true
  EnforcedStyle: single_quotes
  ConsistentQuotesInMultiline: false
  SupportedStyles:
    - single_quotes
    - double_quotes
Layout/TrailingWhitespace:
  Enabled: true
SketchupSuggestions/OperationName:
  Enabled: true

#
Layout/EmptyLinesAroundModuleBody:
  Enabled: false
Layout/EmptyLinesAroundClassBody:
  Enabled: false
Layout/EndAlignment:
  Enabled: true
Layout/FirstMethodArgumentLineBreak:
  Enabled: true

#
Style/Documentation:
  Enabled: false  
Style/FrozenStringLiteralComment:
  Enabled: false  
Lint/UselessAssignment:
  Enabled: true
Lint/ShadowingOuterLocalVariable:
  Enabled: true
Lint/DuplicateMethods:
  Enabled: true

#
Naming/MethodName:
  Enabled: false
Naming/MethodParameterName:
  Enabled: false
Style/BlockDelimiters:
  Enabled: true  # Enforces `{}` vs `do...end` usage
Style/HashSyntax:
  Enabled: false  # Prefer `key: value` over `:key => value`
Style/RedundantFileExtensionInRequire:
  Enabled: true

Security:
  Enabled: true
# These reduced offenses. May need disable/enable to find again.
Metrics/AbcSize:
  Enabled: false
Metrics/ClassLength:
  Enabled: false
Metrics/MethodLength:
  Enabled: false
Metrics/ModuleLength:
  Enabled: false

Metrics/ParameterLists:
  Enabled: true
  Max: 5
  CountKeywordArgs: false

Metrics/CyclomaticComplexity:
  Enabled: true
  Max: 12

Metrics/PerceivedComplexity:
  Enabled: true
  Max: 12

Thanks. This one should be ok now.

window_crafter_v1.4.0.rbz (123.6 KB)

I ran again: 9 files inspected, 2231 offenses detected, 2050 offenses autocorrectable

Most look like style and layout.

I could give you the dump but there’s probably more value in running RuboCop yourself. I’d be curious to know which cops you prefer and why or even just to compare your results with the same cops enabled.

I don’t know. On my side, it says zero offenses found. This what ChatGPT said:

If someone extracts the .rbz somewhere else and runs RuboCop without --config .rubocop.yml, RuboCop uses its default cops. That flags thousands of style/layout/metrics things: single vs double quotes, hash alignment, long methods, line length, module length, etc. That matches the screenshot.

So their result is not saying the plugin has 2231 real correctness problems. It means they ran with default or different cops. Their line “compare your results with the same cops enabled” is the key: they know the cop set may not match.

You ran RuboCop? With your own .rubocop.yml? If so I’d like to try it on my side. If you ran with mine I would have thought we’d get the same results. Visual inspection alone would suggest you would have some offenses when you ran. Just to mention, I don’t know if my cops are ‘optimal’ or even ‘good’. I’ve silenced some in the past but updated recently and have been trying to land on a good set up. For some of them I resisted, like double quotes, which I happen to find more readable… but RuboCop won out and convinced me in the end.

I did not actually run it myself. I asked Claude and ChatGPT to do it on my behalf, since they have access to and control over my terminal.

so you asked a pair of tools known to be lying to cover their bums to run the tool supposed to find problems in their code and they said there was no problem ?

well then :slight_smile:
you can’t delegate everything.

ChatGPT did not create this app, so it would have no reason to cover anything up if that were the case.

I think somewhere @thomthom had a YAML file that omitted a bunch of the subjective style rules.

Check the rules YAML in:

Ah! They could fix the issues if you/they had the offenses. RuboCop is command line, but it needs to installed/configured first.

Here is a recent post if you want to pursue it:
`rubocop-sketchup` 2.0.0 released - Developers / Developer Announcements - SketchUp Community

Dan, do you have thoughts on a ‘balanced’ set up? ParameterLists, CyclomaticComplexity, and PerceivedComplexity came up for me and I questioned how strict I ought to be.

Well actually I find most of the rules subjective without good reasons stated.

( ... more detailed response for 'codeheads' ... click to expand ... )

I’ve got 40 years of experience so I don’t use it myself. I don’t even use a debugger as Ruby itself outputs very informational exception messages. A good editor with AutoComplete is enough for me.

Don’t get me wrong I do take some of the advice from the bbatsov rules posted at GitHub, but many are just nickpicking.

Most of the time, no one else but the author is going to read the code. So only errors that violate EW rules of namespacing (interference with other extensions) or that modify core Ruby or API modules and Classes directly need to be flagged and corrected.

It is a whole other “ballgame” if the code is a group or community project.


Complexity

So while coding, if even I am having to spend extra brainpower keeping track of what a complex method is doing, I feel then that it’s time to break it up into multiple methods. The “offenses” that Rubocop spits out can be a good flag for the author to take a look at such methods. As code authors we often have to return later to fix a bug or add improvements and then we spend extra time relearning was it was were were thinking whilst writing complex methods. So smaller methods and good commenting in the code will help you later.

I think that a score of 7 or 8 will spit out a warning. Only using rubocop for awhile and coding with the SketchUp API for awhile can give you insight into whether the trigger level are too high or too low.


ParameterLists

For SketchUp coding there are many API methods that use a lot of keyword (named) arguments. The UI dialog class constructors or file export methods come to mind.

If you are subclassing, you may not have the option of omitting these. I would suggest setting CountKeywordArgs: false at the least. You can also define a separate limit for optional arguments via MaxOptionalParameters: to allow for more flexibility in method signatures that rely heavily on default values.

But it is true that long method parameter lists become unwieldly and is a sign that a method is doing too much. I’ve done what is suggested in the past of breaking the method up into smaller methods, or collecting the data arguments into a hash and passing that in then perhaps having a few named control arguments follow the hash.

I think the default limit is 5, but in practice if the method signature line approaches 80 characters, my mind thinks that is too much, especially for methods other coders would use.
But if it is only my code and used within a single extension, I have to decide whether the benefit outweighs the cost of constructing a hash to make the call and then deconstructing the hash within method to get variables. That construct/deconstruct is going to take time.

If the code is within an instance, you have the option of using @instance_vars instead of passing state around between methods. I know there are those who frown upon this, but it is what instance variables were designed for. (For the record, a module is an instance of class Module and can itself have instance methods.)
Also, Ruby passes mutable objects [Arrays and Hashes] as references anyway, so you can mutate the original from inside the receiving method. But immutable objects can also be used as local variables inside the method and be reassigned to local values. (It depends upon what method is used.)
So if the arguments are shared anyway, why not take advantage of instance variables and make your life easier?
The debate is going to go like: “The parameter list is a declaration of what values the method uses or may mutate.” My retort would be … Use method descriptions and comments for this.