Return C++ SULayerRef to Ruby?

I’m just toying with some ideas for .dll SketchUp plugins. One thing I wanted to try was importing the Layers of a model on disk to the current open model.

I am currently able to return an Array of Layer names as Strings, but is it possible for the c++ extension to return an Array of real Sketchup::Layer objects to the ruby code?

An example Ruby code would be:

require "MyExt"

# Get Layer list from model on disc.
external_layers = MyExt.get_layers("c:/user/jim/model.skp")

# Add external Layers to current model.
external_layers.each do |layer|
    new_layer = Sketechup.active_model.layers.add(layer.name)
    new_layer.color= layer.color
end

I don’t think so.
But what you can do with the C API s create a copy form the model with the correct layers, remove all entities, crete a simple face for each layer you want to import and place it on this layer. Now import this new model with ruby as a definition and all layers will be imported. Delete the definition.

Thanks @Guy. I have updated my code example to better express my intentions.

If I can’t get a reference to the external Layers or Layer objects directly, then I can always just return the layer names and materials as a collection of standard Ruby types (Strings and numbers.)

Here’s my test result using only Layer names:

Importing Layers from an external model:

Why is the used method not good enough?
We use the described method with the C API because we need the material assigned to the layer and in Ruby we can only set the layer color not the layer material ruby.

It is good enough. I am not a pro programmer - only experimenting. I don’t know what is possible. I thought if I can get a referene to a Layer object, then I wouldn’t need to write the code to get the layer’s name or color because those methods already exist.

I did change my code example again from layer.material to layer.color for correctness.

Jim you have a error in your code:

Sketechup.active_model.add_layer(layer.name) → Sketchup.active_model.add_layer(layer.name)

I see, thanks - fixed.

My idea is to be able to work with a model on disk using the same or similar methods that the SketchUp API uses on the active model. To be able to read and write models and model data directly to and from .skp files from SketchUp.

external_model = model_from_file("/model.skp")
ents = external_model.entities
ents.add_line([0,0], [0,10])
external_model.active_view.camera = Sketchup.active_model.active_view.camera
external_model.active_view.save_image("/image.png")
external_model.save
external_model.close

FYI

From the Ruby-side it is not possible to construct a valid Sketchup::Layer instance independent of a Sketchup::Layers collection, which must be owned by a valid Sketchup::Model instance.
Ie:

l = Sketchup::Layer::new

<Sketchup::Layer:0x00000008754a10>

l.inspect

<Sketchup::Layer:0x00000008754a10>

l.name

Error: #<TypeError: wrong argument type (expected Sketchup::Layer)>

l.name="Dan"

Error: #<TypeError: wrong argument type (expected Sketchup::Layer)>

l.valid?

false


So, it doesn’t seem to be any advantage to create Ruby-side references for the external model’s objects. Ie, you’ll still need to use the active_mode.layers.add() method passing in a string from the external layer list. Then set it’s color.

It would be very interesting if you could also import the layer material & texture, and assign it to the new active model’s layer via a C-side function.

@Guy I’ve done what you explain, except I’ve just put Cpoints on the layers to force the import from a component file.

Doing this externally to SketchUp is called “headless mode.” But I don’t think the SDK has all the bells and whistles, re: geometry cleanup, etc. It definitely does not have the editing tools.

There have been ppl who have come looking for this in the past. They basically did not like the SketchUp UI, and wanted to wrap the SKP engine within their own GUI.

Doing it from within SketchUp… Thomas has told me most of the engine’s functions are written to assume the active model as the target, and that some (most?) of the functions do not even allow passing a model reference into them. Ie, they are hard-coded to act upon the active model. (Which is why we we are not yet given an API models collection that has non-active model references.)

So, I think it will be difficult to impossible to have API methods act upon an external model or it’s objects.

[scratching head in bemusement] SketchUp already does this quite well. Both manually and per-extensions.

Processing extra models, in the same process as SketchUp, means they’d have to share memory with the active model.

Now that is not to say that a better layer import function would be nice. I see that the C API has a function to get a layer’s material. If that material’s texture and properties could be extracted and used to assign to the new layer in the active model, that’d be a step forward for sure.

I have also thought about command line tools, that could do some batch work on skp files. I’m sure there is some people that’d find that useful.

The Ruby API layers needs to come from the model - you can’t have standalone Ruby Layers like you can in C.
You could wrap the properties of the C layer object and recreate in Ruby - that’s about what you can do right now. (Though you might as well just use a plain struct instead of an actual SULayersRef.)

1 Like

No Thomas you can do this only limited. In Ruby you can’t set the layer texture! (We asked you a million times to implement this feature!) But we don’t need it anymore because we finally workaround this last week with the use of the C-API where you can set a material to the layer and not only a color.