diff --git a/README.md b/README.md index 0df90c5..fa65459 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,12 @@ The SketchUp C API is much more limmited than the ruby api. There is no gui eve * Definition List * Entity * Material +* Drawingelement # Partially implemented classes * Attribute Dictionaries * Behavior * Component Instance -* Drawing Element * Entities * Materials * Model diff --git a/ext/drawing_element.c b/ext/drawing_element.c index b35e725..f50b8c5 100644 --- a/ext/drawing_element.c +++ b/ext/drawing_element.c @@ -1,11 +1,146 @@ #include #include +#include #include #include +static VALUE Sketchup_DrawingElement_bounds(VALUE self) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + struct SUBoundingBox3D* bbox = 0; + SUDrawingElementGetBoundingBox(drawing_element, bbox); + return Data_Make_Struct(rb_path2class(GEOM_BOUNDINGBOX), struct SUBoundingBox3D, 0, RUBY_DEFAULT_FREE, bbox); +} + +static VALUE Sketchup_DrawingElement_Get_casts_shadows(VALUE self) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + bool casts_shadows_flag = false; + SUDrawingElementGetCastsShadows(drawing_element, &casts_shadows_flag); + return casts_shadows_flag ? Qtrue : Qfalse; +} + +static VALUE Sketchup_DrawingElement_Set_casts_shadows(VALUE self, VALUE casts_shadows_flag) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SUDrawingElementSetCastsShadows(drawing_element, RTEST(casts_shadows_flag)); + return casts_shadows_flag; +} + +static VALUE Sketchup_DrawingElement_Get_receives_shadows(VALUE self) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + bool receives_shadows_flag = false; + SUDrawingElementGetReceivesShadows(drawing_element, &receives_shadows_flag); + return receives_shadows_flag ? Qtrue : Qfalse; +} + +static VALUE Sketchup_DrawingElement_Set_receives_shadows(VALUE self, VALUE receives_shadows_flag) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SUDrawingElementSetReceivesShadows(drawing_element, RTEST(receives_shadows_flag)); + return receives_shadows_flag; +} + +static VALUE Sketchup_DrawingElement_Get_hidden(VALUE self) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + bool hide_flag = false; + SUDrawingElementGetHidden(drawing_element, &hide_flag); + return hide_flag ? Qtrue : Qfalse; +} + +static VALUE Sketchup_DrawingElement_Set_hidden(VALUE self, VALUE hide_flag) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SUDrawingElementSetHidden(drawing_element, RTEST(hide_flag)); + return hide_flag; +} + +static VALUE Sketchup_DrawingElement_Get_visible(VALUE self) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + bool hide_flag = false; + SUDrawingElementGetHidden(drawing_element, &hide_flag); + return hide_flag ? Qfalse : Qtrue; +} + +static VALUE Sketchup_DrawingElement_Set_visible(VALUE self, VALUE visible_flag) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SUDrawingElementSetHidden(drawing_element, RTEST(visible_flag)); + return visible_flag; +} + +static VALUE Sketchup_DrawingElement_Get_material(VALUE self) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SUMaterialRef material = SU_INVALID; + SUDrawingElementGetMaterial(drawing_element, &material); + if (SUIsInvalid(material)) + return Qnil; + return Data_Wrap_Struct(rb_path2class(SKETCHUP_MATERIAL), 0, 0, material.ptr); +} + +static VALUE Sketchup_DrawingElement_Set_material(VALUE self, VALUE material) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + if (rb_type(material) == T_NIL) + { + SUMaterialRef empty_material = SU_INVALID; + SUDrawingElementSetMaterial(drawing_element, empty_material); + return Qnil; + } + if (!rb_obj_is_kind_of(material, rb_path2class(SKETCHUP_MATERIAL))) + rb_raise(rb_eTypeError, "Wrong type of object given"); + + SUMaterialRef drawing_element_material = {DATA_PTR(material)}; + SUDrawingElementSetMaterial(drawing_element, drawing_element_material); + return material; +} + +static VALUE Sketchup_DrawingElement_Get_layer(VALUE self) +{ + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SULayerRef layer = SU_INVALID; + SUDrawingElementGetLayer(drawing_element, &layer); + return Data_Wrap_Struct(rb_path2class(SKETCHUP_LAYER), 0, 0, layer.ptr); +} + +static VALUE Sketchup_DrawingElement_Set_layer(VALUE self, VALUE layer) +{ + if (rb_type(layer) == T_NIL) + { + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SULayerRef drawing_element_layer = SU_INVALID; + SUDrawingElementSetLayer(drawing_element, drawing_element_layer); + return Qnil; + } + if (!rb_obj_is_kind_of(layer, rb_path2class(SKETCHUP_LAYER))) + rb_raise(rb_eArgError, "Wrong type of object given"); + + SUDrawingElementRef drawing_element = {DATA_PTR(self)}; + SULayerRef drawing_element_layer = {DATA_PTR(layer)}; + SUDrawingElementSetLayer(drawing_element, drawing_element_layer); + return layer; +} + VALUE DrawingElement_Init(VALUE Sketchup, VALUE Sketchup_Entity) { VALUE Sketchup_DrawingElement = rb_define_class_under(Sketchup, DRAWINGELEMENT, Sketchup_Entity); rb_undef_alloc_func(Sketchup_DrawingElement); + rb_define_method(Sketchup_DrawingElement, "bounds", Sketchup_DrawingElement_bounds, 0); + rb_define_method(Sketchup_DrawingElement, "casts_shadows?", Sketchup_DrawingElement_Get_casts_shadows, 0); + rb_define_method(Sketchup_DrawingElement, "casts_shadows=", Sketchup_DrawingElement_Set_casts_shadows, 1); + rb_define_method(Sketchup_DrawingElement, "receives_shadows?", Sketchup_DrawingElement_Get_receives_shadows, 0); + rb_define_method(Sketchup_DrawingElement, "receives_shadows=", Sketchup_DrawingElement_Set_receives_shadows, 1); + rb_define_method(Sketchup_DrawingElement, "hidden?", Sketchup_DrawingElement_Get_hidden, 0); + rb_define_method(Sketchup_DrawingElement, "hidden=", Sketchup_DrawingElement_Set_hidden, 1); + rb_define_method(Sketchup_DrawingElement, "visible?", Sketchup_DrawingElement_Get_visible, 0); + rb_define_method(Sketchup_DrawingElement, "visible=", Sketchup_DrawingElement_Set_visible, 1); + rb_define_method(Sketchup_DrawingElement, "material", Sketchup_DrawingElement_Get_material, 0); + rb_define_method(Sketchup_DrawingElement, "material=", Sketchup_DrawingElement_Set_material, 1); + rb_define_method(Sketchup_DrawingElement, "layer", Sketchup_DrawingElement_Get_layer, 0); + rb_define_method(Sketchup_DrawingElement, "layer=", Sketchup_DrawingElement_Set_layer, 1); return Sketchup_DrawingElement; } \ No newline at end of file diff --git a/ext/entities.c b/ext/entities.c index 3bcb048..d17fed4 100644 --- a/ext/entities.c +++ b/ext/entities.c @@ -3,10 +3,23 @@ #include #include +void Sketchup_Entities_Iterator(SUFaceRef face, void* _) +{ + rb_yield(Data_Wrap_Struct(rb_path2class(SKETCHUP_FACE), 0, 0, face.ptr)); +} + +static VALUE Sketchup_Entities_each(VALUE self) +{ + SUEntitiesRef entities = {DATA_PTR(self)}; + FOREACH(SUEntitiesGetNumFaces, SUEntitiesGetFaces, SUFaceRef, entities, Sketchup_Entities_Iterator, 0); + return self; +} VALUE Entities_Init(VALUE Sketchup, VALUE rb_cObject) { VALUE Sketchup_Entities = rb_define_class_under(Sketchup, ENTITIES, rb_cObject); rb_undef_alloc_func(Sketchup_Entities); + rb_include_module(Sketchup_Entities, rb_mEnumerable); + rb_define_method(Sketchup_Entities, "each", Sketchup_Entities_each, 0); return Sketchup_Entities; } \ No newline at end of file diff --git a/ext/not_implemented.c b/ext/not_implemented.c new file mode 100644 index 0000000..4b675f9 --- /dev/null +++ b/ext/not_implemented.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +VALUE BoundingBox_Init(VALUE Geom, VALUE Sketchup_Object) +{ + VALUE Geom_BoundingBox = rb_define_class_under(Geom, BOUNDINGBOX, Sketchup_Object); + rb_undef_alloc_func(Geom_BoundingBox); + return Geom_BoundingBox; +} + +VALUE Face_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_Face = rb_define_class_under(Sketchup, FACE, DrawingElement); + rb_undef_alloc_func(Sketchup_Face); + return Sketchup_Face; +} + +VALUE Layer_Init(VALUE Sketchup, VALUE Entity) +{ + VALUE Sketchup_Layer = rb_define_class_under(Sketchup, LAYER, Entity); + rb_undef_alloc_func(Sketchup_Layer); + return Sketchup_Layer; +} + +VALUE ConstructionLine_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_ConstructionLine = rb_define_class_under(Sketchup, CONSTRUCTIONLINE, DrawingElement); + rb_undef_alloc_func(Sketchup_ConstructionLine); + return Sketchup_ConstructionLine; +} + +VALUE ConstructionPoint_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_ConstructionPoint = rb_define_class_under(Sketchup, CONSTRUCTIONPOINT, DrawingElement); + rb_undef_alloc_func(Sketchup_ConstructionPoint); + return Sketchup_ConstructionPoint; +} + +VALUE Dimension_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_Dimension = rb_define_class_under(Sketchup, DIMENSION, DrawingElement); + rb_undef_alloc_func(Sketchup_Dimension); + return Sketchup_Dimension; +} + +VALUE Edge_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_Edge = rb_define_class_under(Sketchup, EDGE, DrawingElement); + rb_undef_alloc_func(Sketchup_Edge); + return Sketchup_Edge; +} + +VALUE Group_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_Group = rb_define_class_under(Sketchup, GROUP, DrawingElement); + rb_undef_alloc_func(Sketchup_Group); + return Sketchup_Group; +} + +VALUE Image_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_Image = rb_define_class_under(Sketchup, IMAGE, DrawingElement); + rb_undef_alloc_func(Sketchup_Image); + return Sketchup_Image; +} + +VALUE SectionPlane_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_SectionPlane = rb_define_class_under(Sketchup, SECTIONPLANE, DrawingElement); + rb_undef_alloc_func(Sketchup_SectionPlane); + return Sketchup_SectionPlane; +} + +VALUE Text_Init(VALUE Sketchup, VALUE DrawingElement) +{ + VALUE Sketchup_Text = rb_define_class_under(Sketchup, TEXT, DrawingElement); + rb_undef_alloc_func(Sketchup_Text); + return Sketchup_Text; +} \ No newline at end of file diff --git a/ext/not_implemented.h b/ext/not_implemented.h new file mode 100644 index 0000000..2e0b5d4 --- /dev/null +++ b/ext/not_implemented.h @@ -0,0 +1,13 @@ +#include + +VALUE BoundingBox_Init(VALUE namespace_object, VALUE parent_class); +VALUE Face_Init(VALUE namespace_object, VALUE parent_class); +VALUE Layer_Init(VALUE namespace_object, VALUE parent_class); +VALUE ConstructionLine_Init(VALUE namespace_object, VALUE parent_class); +VALUE ConstructionPoint_Init(VALUE namespace_object, VALUE parent_class); +VALUE Dimension_Init(VALUE namespace_object, VALUE parent_class); +VALUE Edge_Init(VALUE namespace_object, VALUE parent_class); +VALUE Group_Init(VALUE namespace_object, VALUE parent_class); +VALUE Image_Init(VALUE namespace_object, VALUE parent_class); +VALUE SectionPlane_Init(VALUE namespace_object, VALUE parent_class); +VALUE Text_Init(VALUE namespace_object, VALUE parent_class); diff --git a/ext/sketchup.c b/ext/sketchup.c index ec85aa9..5863920 100644 --- a/ext/sketchup.c +++ b/ext/sketchup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include SUModelRef active_model = SU_INVALID; @@ -82,8 +83,21 @@ void Init_sketchup() { AttributeDictionaries_Init(Sketchup, Sketchup_Entity); Texture_Init(Sketchup, Sketchup_Entity); Behavior_Init(Sketchup, Sketchup_Entity); + Layer_Init(Sketchup, Sketchup_Entity); + VALUE Geom = rb_define_module(GEOM); + BoundingBox_Init(Geom, rb_cObject); + VALUE Sketchup_DrawingElement = DrawingElement_Init(Sketchup, Sketchup_Entity); ComponentInstance_Init(Sketchup, Sketchup_DrawingElement); ComponentDefinition_Init(Sketchup, Sketchup_DrawingElement); + Face_Init(Sketchup, Sketchup_DrawingElement); + ConstructionLine_Init(Sketchup, Sketchup_DrawingElement); + ConstructionPoint_Init(Sketchup, Sketchup_DrawingElement); + Dimension_Init(Sketchup, Sketchup_DrawingElement); + Edge_Init(Sketchup, Sketchup_DrawingElement); + Group_Init(Sketchup, Sketchup_DrawingElement); + Image_Init(Sketchup, Sketchup_DrawingElement); + SectionPlane_Init(Sketchup, Sketchup_DrawingElement); + Text_Init(Sketchup, Sketchup_DrawingElement); } \ No newline at end of file diff --git a/ext/utils.h b/ext/utils.h index 51b28b7..a576c11 100644 --- a/ext/utils.h +++ b/ext/utils.h @@ -1,7 +1,11 @@ #include #ifndef UTILS_H +#ifdef TEXT +#undef TEXT +#endif //TEXT #define SKETCHUP "Sketchup" +#define GEOM "Geom" #define MODEL "Model" #define MATERIAL "Material" #define MATERIALS "Materials" @@ -16,6 +20,17 @@ #define ATTRIBUTEDICTIONARIES "AttributeDictionaries" #define DRAWINGELEMENT "DrawingElement" #define BEHAVIOR "Behavior" +#define BOUNDINGBOX "BoundingBox" +#define FACE "Face" +#define LAYER "Layer" +#define CONSTRUCTIONLINE "ConstructionLine" +#define CONSTRUCTIONPOINT "ConstructionPoint" +#define DIMENSION "Dimension" +#define EDGE "Edge" +#define IMAGE "Image" +#define SECTIONPLANE "SectionPlane" +#define GROUP "Group" +#define TEXT "Text" #define SKETCHUP_MATERIAL SKETCHUP "::" MATERIAL #define SKETCHUP_MATERIALS SKETCHUP "::" MATERIALS #define SKETCHUP_TEXTURE SKETCHUP "::" TEXTURE @@ -28,6 +43,17 @@ #define SKETCHUP_ATTRIBUTEDICTIONARIES SKETCHUP "::" ATTRIBUTEDICTIONARIES #define SKETCHUP_DEFINITIONLIST SKETCHUP "::" DEFINITIONLIST #define SKETCHUP_BEHAVIOR SKETCHUP "::" BEHAVIOR +#define GEOM_BOUNDINGBOX GEOM "::" BOUNDINGBOX +#define SKETCHUP_FACE SKETCHUP "::" FACE +#define SKETCHUP_LAYER SKETCHUP "::" LAYER +#define SKETCHUP_CONSTRUCTIONLINE SKETCHUP "::" CONSTRUCTIONLINE +#define SKETCHUP_CONSTRUCTIONPOINT SKETCHUP "::" CONSTRUCTIONPOINT +#define SKETCHUP_DIMENSION SKETCHUP "::" DIMENSION +#define SKETCHUP_EDGER SKETCHUP "::" EDGE +#define SKETCHUP_IMAGE SKETCHUP "::" IMAGE +#define SKETCHUP_SECTIONPLANE SKETCHUP "::" SECTIONPLANE +#define SKETCHUP_GROUP SKETCHUP "::" GROUP +#define SKETCHUP_TEXT SKETCHUP "::" TEXT #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wbackslash-newline-escape" diff --git a/test/test_drawing_element.rb b/test/test_drawing_element.rb new file mode 100644 index 0000000..4bcead6 --- /dev/null +++ b/test/test_drawing_element.rb @@ -0,0 +1,57 @@ +require 'minitest/autorun' +require 'sketchup' + +class TestDrawingElement < Minitest::Test + + def setup + Sketchup.open_file("#{ENV['TEST_RESOURCES']}/Untitled.skp") + @drawing_element = Sketchup.active_model.definitions.find { |d| d.name == 'Heather' } + end + + def test_object + assert_kind_of(Sketchup::DrawingElement, @drawing_element) + end + + def test_bounds + assert_kind_of(Geom::BoundingBox, @drawing_element.bounds) + end + + def test_cast_shadows + assert(@drawing_element.entities.grep(Sketchup::Face).first.casts_shadows = true) + assert(@drawing_element.entities.grep(Sketchup::Face).first.casts_shadows?) + refute(@drawing_element.entities.grep(Sketchup::Face).first.casts_shadows = false) + refute(@drawing_element.entities.grep(Sketchup::Face).first.casts_shadows?) + end + + def test_hidden + refute(@drawing_element.hidden?) + assert(@drawing_element.hidden = true) + end + + def test_layer + assert_kind_of(Sketchup::Layer, @drawing_element.layer) + assert_nil(@drawing_element.layer = nil) + assert_raises(ArgumentError) { + @drawing_element.layer = Object.new + } + end + + def test_material + assert_nil(@drawing_element.material) + assert_nil(@drawing_element.material = nil) + assert_raises(TypeError) { + @drawing_element.material = Object.new + } + end + + def test_receives_shadows + assert(@drawing_element.receives_shadows?) + assert(@drawing_element.receives_shadows = true) + end + + def test_visible + assert(@drawing_element.visible?) + refute(@drawing_element.visible = false) + end + +end