Module: MSPhysics

Defined in:
RubyExtension/MSPhysics.rb,
RubyExtension/MSPhysics/hit.rb,
RubyExtension/MSPhysics/body.rb,
RubyExtension/MSPhysics/gear.rb,
RubyExtension/MSPhysics/main.rb,
RubyExtension/MSPhysics/joint.rb,
RubyExtension/MSPhysics/world.rb,
RubyExtension/MSPhysics/entity.rb,
RubyExtension/MSPhysics/contact.rb,
RubyExtension/MSPhysics/joint_fixed.rb,
RubyExtension/MSPhysics/joint_hinge.rb,
RubyExtension/MSPhysics/joint_motor.rb,
RubyExtension/MSPhysics/joint_plane.rb,
RubyExtension/MSPhysics/joint_servo.rb,
RubyExtension/MSPhysics/joint_piston.rb,
RubyExtension/MSPhysics/joint_slider.rb,
RubyExtension/MSPhysics/joint_spring.rb,
RubyExtension/MSPhysics/joint_corkscrew.rb,
RubyExtension/MSPhysics/joint_universal.rb,
RubyExtension/MSPhysics/joint_up_vector.rb,
RubyExtension/MSPhysics/controller_context.rb,
RubyExtension/MSPhysics/joint_curvy_piston.rb,
RubyExtension/MSPhysics/joint_curvy_slider.rb,
RubyExtension/MSPhysics/joint_point_to_point.rb,
RubyExtension/MSPhysics/joint_ball_and_socket.rb

Overview

Since:

  • 1.0.0

Defined Under Namespace

Modules: Collision, ControlPanel, Dialog, Materials, Replay, Settings Classes: BallAndSocket, Body, BodyContext, CommonContext, Contact, ControllerContext, Corkscrew, CurvyPiston, CurvySlider, Entity, Fixed, Gear, GearConnectionTool, Hinge, Hit, Joint, JointConnectionTool, JointTool, Material, Motor, Piston, Plane, PointToPoint, SceneData, ScriptException, Servo, Simulation, Slider, Spring, Universal, UpVector, World

Constant Summary collapse

NAME =

Since:

  • 1.0.0

'MSPhysics'.freeze
VERSION =

Since:

  • 1.0.0

'1.1.0'.freeze
RELEASE_DATE =

Since:

  • 1.0.0

'January 1, 2019'.freeze
EPSILON =

Since:

  • 1.0.0

1.0e-6
SHAPES =

Since:

  • 1.0.0

{
  0 => 'Null',
  1 => 'Box',
  2 => 'Sphere',
  3 => 'Cone',
  4 => 'Cylinder',
  5 => 'Chamfer Cylinder',
  6 => 'Capsule',
  7 => 'Convex Hull',
  8 => 'Compound',
  9 => 'Static Mesh'
}.freeze
SHAPE_DIRS =

Since:

  • 1.0.0

{
  0 => 'X-axis',
  1 => 'Y-axis',
  2 => 'Z-axis'
}.freeze
JOINT_ID_TO_NAME =

Since:

  • 1.0.0

{
  0  => 'None',
  1  => 'Hinge',
  2  => 'Motor',
  3  => 'Servo',
  4  => 'Slider',
  5  => 'Piston',
  6  => 'UpVector',
  7  => 'Spring',
  8  => 'Corkscrew',
  9  => 'BallAndSocket',
  10 => 'Universal',
  11 => 'Fixed',
  12 => 'CurvySlider',
  13 => 'CurvyPiston',
  14 => 'Plane',
  15 => 'PointToPoint'
}.freeze
JOINT_ID_TO_FILE_NAME =

Since:

  • 1.0.0

{
  0  => 'none',
  1  => 'hinge',
  2  => 'motor',
  3  => 'servo',
  4  => 'slider',
  5  => 'piston',
  6  => 'up_vector',
  7  => 'spring',
  8  => 'corkscrew',
  9  => 'ball_and_socket',
  10 => 'universal',
  11 => 'fixed',
  12 => 'curvy_slider',
  13 => 'curvy_piston',
  14 => 'plane',
  15 => 'point_to_point'
}.freeze
JOINT_NAMES =

Since:

  • 1.0.0

JOINT_ID_TO_NAME.values.freeze
JOINT_FILE_NAMES =

Since:

  • 1.0.0

JOINT_ID_TO_FILE_NAME.values.freeze
MASS_CONTROLS =

Since:

  • 1.0.0

{
  1 => 'by Density',
  2 => 'by Mass'
}.freeze
MAGNET_MODES =

Since:

  • 1.0.0

{
  1 => 'Mode 1',
  2 => 'Mode 2'
}.freeze
BODY_TYPES =

Since:

  • 1.0.0

{
  0 => 'Dynamic',
  1 => 'Kinematic'
}.freeze
BODY_STATES =

Since:

  • 1.0.0

[
  'Ignore',
  'Static',
  'Frozen',
  'Magnetic',
  'Collidable',
  'Auto Sleep',
  'Continuous Collision',
  'Enable Friction',
  'Enable Script',
  'Enable Gravity',
  'Enable Thruster',
  'Enable Emitter',
  'Thruster Lock Axes',
  'Emitter Lock Axes',
  'Emitter Recoil'
].freeze
BODY_CON_STATES =

Since:

  • 1.0.0

[
  'Clear Ignore Flag',
  'Movable',
  'Non-Frozen',
  'Non-Magnetic',
  'Non-Collidable',
  'No Auto Sleep',
  'No Continuous Collision',
  'Disable Friction',
  'Disable Script',
  'Disable Gravity',
  'Disable Thruster',
  'Disable Emitter',
  'No Thruster Lock Axes',
  'No Emitter Lock Axes',
  "No Emitter Recoil"
].freeze
MATERIALS =

Coefficients are defined from material to material contacts. Material to another material coefficients are automatically calculated by averaging out the coefficients of both. Many coefficient values are estimated, averaged up, made up, and not accurate. name => [ density (kg/m^3), static friction, kinetic friction, elasticity, softness ]

Since:

  • 1.0.0

{
  'Aluminium'         => [2700, 0.42, 0.34, 0.30, 0.01],
  'Brass'             => [8730, 0.35, 0.24, 0.40, 0.01],
  'Brick'             => [1920, 0.60, 0.55, 0.20, 0.01],
  'Bronze'            => [8200, 0.36, 0.27, 0.60, 0.01],
  'Cadnium'           => [8640, 0.79, 0.46, 0.60, 0.01],
  'Cast Iron'         => [7300, 0.51, 0.40, 0.60, 0.01],
  'Chromium'          => [7190, 0.46, 0.30, 0.60, 0.01],
  'Cobalt'            => [8746, 0.56, 0.40, 0.60, 0.01],
  'Concrete'          => [2400, 0.62, 0.56, 0.20, 0.01],
  'Glass'             => [2800, 0.90, 0.72, 0.4, 0.01],
  'Copper'            => [8940, 0.55, 0.40, 0.60, 0.01],
  'Gold'              => [19320, 0.49, 0.39, 0.60, 0.01],
  'Graphite'          => [2230, 0.18, 0.14, 0.10, 0.01],
  'Ice'               => [916, 0.01, 0.01, 0.10, 0.01],
  'Nickel'            => [8900, 0.53, 0.44, 0.60, 0.01],
  'Plastic'           => [1000, 0.35, 0.30, 0.69, 0.01],
  'Rubber'            => [1100, 1.16, 1.16, 0.01, 0.01],
  'Silver'            => [10500, 0.50, 0.40, 0.60, 0.01],
  'Steel'             => [8050, 0.31, 0.23, 0.60, 0.01],
  'Teflon'            => [2170, 0.04, 0.03, 0.10, 0.01],
  'Titanium'          => [4500, 0.36, 0.30, 0.40, 0.01],
  'Tungsten Carbide'  => [19600, 0.22, 0.15, 0.40, 0.01],
  'Wood'              => [700, 0.50, 0.25, 0.40, 0.01],
  'Zinc'              => [7000, 0.60, 0.50, 0.60, 0.01]
}.freeze
DEFAULT_SIMULATION_SETTINGS =

Since:

  • 1.0.0

{
  :solver_model               => 16,      # 1 - 64
  :joint_algorithm            => 2,       # 0 - accurate; 1 - don't use; 2 - fast.
  :update_rate                => 2,       # 1 - 100
  :update_timestep            => 1/60.0,  # 1/30 - 1/1200, in seconds
  :gravity                    => -9.801,  # in m/s/s along Z-axis
  :material_thickness         => 0.002,   # thickness b/w 0.0 and 1/32 meters
  :contact_merge_tolerance    => 0.005,   # 0.001+
  :continuous_collision_check => false,   # boolean
  :full_screen_mode           => false,   # boolean
  :ignore_hidden_instances    => false,   # boolean
  :game_mode                  => false,   # boolean
  :hide_joint_layer           => false,   # boolean
  :undo_on_end                => false,   # boolean
  :key_nav_state              => 0,       # 0 - off; 1 - normal; 2 - upright.
  :key_nav_velocity           => 40.0,    # in m/s
  :key_nav_omega              => 1.0,     # in rad/s
  :key_nav_atime              => 0.15,    # in seconds
  :animate_scenes_state       => 0,       # 0 - off; 1 - one way; 2 - repeat forth and back; 3 - loop around.
  :animate_scenes_delay       => 0.0,     # in seconds
  :animate_scenes_reversed    => false    # boolean
}.freeze
DEFAULT_BODY_SETTINGS =

Since:

  • 1.0.0

{
  :type                   => 0,
  :shape_id               => 8,
  :shape_dir              => 0,
  :material_name          => 'Default',
  :mass_control           => 1,
  :density                => 700,
  :mass                   => 1.0,
  :static_friction        => 0.90,
  :kinetic_friction       => 0.50,
  :enable_friction        => true,
  :elasticity             => 0.40,
  :softness               => 0.10,
  :linear_damping         => 0.001,
  :angular_damping        => 0.001,
  :magnet_mode            => 1,
  :magnet_force           => 0.00,
  :magnet_range           => 0.00,
  :magnet_strength        => 0.00,
  :magnetic               => false,
  :enable_script          => true,
  :static                 => false,
  :frozen                 => false,
  :collidable             => true,
  :auto_sleep             => true,
  :continuous_collision   => false,
  :thruster_lock_axes     => true,
  :enable_thruster        => true,
  :emitter_lock_axes      => true,
  :emitter_recoil         => false,
  :emitter_rate           => 0.1,
  :emitter_lifetime       => 1.0,
  :emitter_delay          => 0.0,
  :enable_emitter         => true,
  :enable_gravity         => true
}.freeze
DEFAULT_BUOYANCY_PLANE_SETTINGS =

Since:

  • 1.0.0

{
  :material_name          => 'MSPhysics Buoyancy',
  :density                => 997.04,
  :viscosity              => 0.015,
  :current_x              => 0,
  :current_y              => 0,
  :current_z              => 0,
  :plane_size             => 10000,
  :color                  => Sketchup::Color.new(40,60,220),
  :alpha                  => 0.7
}.freeze
CURSORS =

Since:

  • 1.0.0

{
  :select                 => 0,
  :select_plus            => 0,
  :select_minus           => 0,
  :select_plus_minus      => 0,
  :hand                   => 0,
  :grab                   => 0,
  :click                  => 0,
  :target                 => 0
}
CURSOR_ORIGINS =

Since:

  • 1.0.0

{
  :select                 => [2,5],
  :select_plus            => [2,5],
  :select_minus           => [2,5],
  :select_plus_minus      => [2,5],
  :hand                   => [2,2],
  :grab                   => [2,2],
  :click                  => [2,2],
  :target                 => [15,15]
}.freeze
EMBEDDED_MUSIC_FORMATS =

Since:

  • 1.0.0

%w(wav aiff riff ogg voc flac mod it xm s3m m4a 669 med mp3 mp2 mid pat).freeze
EMBEDDED_SOUND_FORMATS =

Since:

  • 1.0.0

%w(wav aiff riff ogg voc mp3 mp2).freeze
JOYSTICK1_AXES =

Since:

  • 1.0.0

%w(leftx lefty leftz rightx righty rightz).freeze
JOYSTICK2_AXES =

Since:

  • 1.0.0

%w(leftx lefty rightx righty).freeze
JOYSTICK1_BUTTONS =

Since:

  • 1.0.0

%w(a b x y lb rb back start leftb rightb).freeze
JOYSTICK2_BUTTONS =

Since:

  • 1.0.0

%w(x a b y lb rb lt rt back start leftb rightb).freeze
DEFAULT_JOINT_SCALE =

Since:

  • 1.0.0

1.0
WATERMARK_COLOR =

Since:

  • 1.0.0

Sketchup::Color.new(126, 42, 168)
DEFAULT_ANGLE_UNITS =

Since:

  • 1.0.0

'deg'.freeze
DEFAULT_POSITION_UNITS =

Since:

  • 1.0.0

'cm'.freeze
SCRIPT_NAME =

Since:

  • 1.0.0

'MSPhysicsScript'.freeze
CONTROLLER_NAME =

Since:

  • 1.0.0

'MSPhysicsController'.freeze
VIEW_UPDATE_TIMESTEP =

Since:

  • 1.0.0

1.0 / 60.0
VIEW_UPDATE_TIMESTEP_INV =

Since:

  • 1.0.0

1.0 / VIEW_UPDATE_TIMESTEP
POSITION_CONVERSION =

Since:

  • 1.0.0

{
  'mm' => 0.001,
  'cm' => 0.01,
  'dm' => 0.1,
  'm'  => 1.0,
  'in' => 0.0254,
  'ft' => 0.3048,
  'yd' => 0.9144
}
ANGLE_CONVERSION =

Since:

  • 1.0.0

{
  'deg' => 1.degrees.to_f,
  'rad' => 1.0
}

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.extensionSketchupExtension (readonly)

Get MSPhysics extension.

Returns:

  • (SketchupExtension)

Since:

  • 1.0.0


30
31
32
# File 'RubyExtension/MSPhysics.rb', line 30

def extension
  @extension
end

Class Method Details

.add_watermark_text(x, y, text, name = 'Watermark', component = 'version_text.skp') ⇒ Sketchup::Text?

Note:

Manually wrap the operation.

Create a watermark text.

Parameters:

  • x (Integer)

    X position on screen.

  • y (Integer)

    Y position on screen.

  • text (String)

    Watermark text.

  • name (String) (defaults to: 'Watermark')

    Watermark name.

  • component (String) (defaults to: 'version_text.skp')

    Watermark component.

Returns:

  • (Sketchup::Text, nil)

    A text object if successful.

Since:

  • 1.0.0


484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'RubyExtension/MSPhysics/main.rb', line 484

def add_watermark_text(x, y, text, name = 'Watermark', component = 'version_text.skp')
  ext_dir = File.dirname(__FILE__)
  ext_dir.force_encoding('UTF-8') unless AMS::IS_RUBY_VERSION_18
  path = File.join(ext_dir, "models/#{component}")
  return unless File.exists?(path)
  model = Sketchup.active_model
  view = model.active_view
  cd = model.definitions.load(path)
  ray = view.pickray(x,y)
  loc = ray[0]+ray[1]
  ci = model.entities.add_instance(cd, Geom::Transformation.new(loc))
  tt = ci.explode.find { |e| e.is_a?(Sketchup::Text) }
  tt.set_text(text)
  tt.set_attribute('MSPhysics', 'Name', name.to_s)
  mat = model.materials['MSPWatermarkText']
  unless mat
    mat = model.materials.add('MSPWatermarkText')
    mat.color = WATERMARK_COLOR
  end
  tt.material = mat
  layer = model.layers['MSPWatermarkText']
  unless layer
    layer = model.layers.add('MSPWatermarkText')
    layer.color = WATERMARK_COLOR if Sketchup.version.to_i > 13
  end
  tt.layer = layer
  tt
end

.add_watermark_text2(x, y, text, name = 'Watermark', component = 'version_text.skp') ⇒ Sketchup::Text?

Note:

Manually wrap the operation.

Create a watermark text without material or layer.

Parameters:

  • x (Integer)

    X position on screen.

  • y (Integer)

    Y position on screen.

  • text (String)

    Watermark text.

  • name (String) (defaults to: 'Watermark')

    Watermark name.

  • component (String) (defaults to: 'version_text.skp')

    Watermark component.

Returns:

  • (Sketchup::Text, nil)

    A text object if successful.

Since:

  • 1.0.0


521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
# File 'RubyExtension/MSPhysics/main.rb', line 521

def add_watermark_text2(x, y, text, name = 'Watermark', component = 'version_text.skp')
  ext_dir = File.dirname(__FILE__)
  ext_dir.force_encoding('UTF-8') unless AMS::IS_RUBY_VERSION_18
  path = File.join(ext_dir, "models/#{component}")
  return unless File.exists?(path)
  model = Sketchup.active_model
  view = model.active_view
  cd = model.definitions.load(path)
  ray = view.pickray(x,y)
  loc = ray[0]+ray[1]
  ci = model.entities.add_instance(cd, Geom::Transformation.new(loc))
  tt = ci.explode.find { |e| e.is_a?(Sketchup::Text) }
  tt.set_text(text)
  tt.set_attribute('MSPhysics', 'Name', name.to_s)
  tt
end

.all_watermark_textsArray<Sketchup::Text>

Get all watermark texts.

Returns:

  • (Array<Sketchup::Text>)

Since:

  • 1.0.0


550
551
552
553
554
555
556
# File 'RubyExtension/MSPhysics/main.rb', line 550

def all_watermark_texts
  texts = []
  Sketchup.active_model.entities.each { |e|
    texts << e if e.is_a?(Sketchup::Text) && e.get_attribute('MSPhysics', 'Name') != nil
  }
  texts
end

.delete_all_attributesvoid

Note:

Manually wrap the operation.

This method returns an undefined value.

Delete MSPhysics attributes from all entities.

Since:

  • 1.0.0


422
423
424
425
426
427
428
429
430
431
432
433
# File 'RubyExtension/MSPhysics/main.rb', line 422

def delete_all_attributes
  model = Sketchup.active_model
  model.definitions.each { |d|
    delete_attributes(d.instances)
  }
  dicts = model.attribute_dictionaries
  if dicts
    dicts.delete('MSPhysics')
    dicts.delete('MSPhysics Sounds')
    dicts.delete('MSPhysics Replay')
  end
end

.delete_attribute(ents, handle, name = nil) ⇒ void

Note:

Manually wrap the operation.

This method returns an undefined value.

Delete attribute value from a collection of entities.

Parameters:

  • ents (Array<Sketchup::Entity>)

    A collection of entities.

  • handle (String)

    Dictionary name.

  • name (String) (defaults to: nil)

    Attribute name.

Since:

  • 1.0.0


393
394
395
396
397
# File 'RubyExtension/MSPhysics/main.rb', line 393

def delete_attribute(ents, handle, name = nil)
  ents.each { |e|
    name ? e.delete_attribute(handle, name) : e.delete_attribute(handle)
  }
end

.delete_attributes(ents) ⇒ void

Note:

Manually wrap the operation.

This method returns an undefined value.

Delete MSPhysics attributes from a collection of entities.

Parameters:

  • ents (Array<Sketchup::Entity>)

    A collection of entities.

Since:

  • 1.0.0


403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'RubyExtension/MSPhysics/main.rb', line 403

def delete_attributes(ents)
  ents.each { |e|
    e.delete_attribute('MSPhysics') if e.get_attribute('MSPhysics', 'Type', 'Body') == 'Body'
    e.delete_attribute('MSPhysics Body')
    #~ e.delete_attribute('MSPhysics Joint')
    dict = e.attribute_dictionary('MSPhysics Joint')
    if dict
      dict.keys.each { k|
        e.delete_attribute('MSPhysics Joint', k) if k != 'Type'
      }
    end
    e.delete_attribute('MSPhysics Script')
    e.delete_attribute('MSPhysics Buoyancy Plane')
  }
end

.duplicate_camera(camera) ⇒ Sketchup::Camera

Create copy of a camera object.

Parameters:

  • camera (Sketchup::Camera)

Returns:

  • (Sketchup::Camera)

Since:

  • 1.0.0


689
690
691
692
693
694
695
696
697
698
699
700
701
702
# File 'RubyExtension/MSPhysics/main.rb', line 689

def duplicate_camera(camera)
  c = Sketchup::Camera.new(camera.eye, camera.target, camera.up)
  c.aspect_ratio = camera.aspect_ratio
  c.perspective = camera.perspective?
  if camera.perspective?
    c.focal_length = camera.focal_length
    c.fov = camera.fov
    c.image_width = camera.image_width
  else
    c.height = camera.height
  end
  c.description = camera.description
  return c
end

.find_watermark_text_by_name(name) ⇒ Sketchup::Text?

Get watermark text by name.

Parameters:

  • name (String)

Returns:

  • (Sketchup::Text, nil)

    A text object if the text exists.

Since:

  • 1.0.0


541
542
543
544
545
546
# File 'RubyExtension/MSPhysics/main.rb', line 541

def find_watermark_text_by_name(name)
  Sketchup.active_model.entities.each { |e|
    return e if e.is_a?(Sketchup::Text) && e.get_attribute('MSPhysics', 'Name') == name.to_s
  }
  nil
end

.get_attribute(ents, handle, name, default_value = nil) ⇒ Object

Get common attribute value from a collection of entities.

Parameters:

  • ents (Array<Sketchup::Entity>)

    A collection of entities.

  • handle (String)

    Dictionary name.

  • name (String)

    Attribute name.

  • default_value (Object) (defaults to: nil)

    The value to return if the attribute value is not found.

Returns:

  • (Object)

    A common attribute value or nil if one of the entity attributes is different from another.

Since:

  • 1.0.0


359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'RubyExtension/MSPhysics/main.rb', line 359

def get_attribute(ents, handle, name, default_value = nil)
  vset = false
  value = nil
  ents.each { |e|
    v = e.get_attribute(handle, name, default_value)
    if vset
      return nil if v != value
    else
      value = v
      vset = true
    end
  }
  return value
end

.get_joint_scaleNumeric

Get physical joint scale.

Returns:

  • (Numeric)

Since:

  • 1.0.0


437
438
439
# File 'RubyExtension/MSPhysics/main.rb', line 437

def get_joint_scale
  Sketchup.active_model.get_attribute('MSPhysics', 'Joint Scale', DEFAULT_JOINT_SCALE).to_f
end

.make_compatible(wrap_op = true) ⇒ void

This method returns an undefined value.

Make model of previous MSPhysics version compatible with this version.

Parameters:

  • wrap_op (Boolean) (defaults to: true)

    Whether to wrap in operation.

Since:

  • 1.0.0


602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
# File 'RubyExtension/MSPhysics/main.rb', line 602

def make_compatible(wrap_op = true)
  model = Sketchup.active_model
  bdict = 'MSPhysics Body'
  # Start operation
  if wrap_op
    op = 'MSPhysics - Making Compatible'
    Sketchup.version.to_i > 6 ? model.start_operation(op, true, false, false) : model.start_operation(op)
  end
  # Make changes
  update_timestep = model.get_attribute('MSPhysics', 'Update Timestep', MSPhysics::DEFAULT_SIMULATION_SETTINGS[:update_timestep]).to_f
  model.definitions.each { |d|
    d.instances.each { |i|
      # Remove unused attributes
      i.delete_attribute(bdict, 'Connect Closest Joints')
      # Replace weight control
      weight_control = i.get_attribute(bdict, 'Weight Control')
      if weight_control
        if i.get_attribute(bdict, 'Mass Control').nil?
          i.set_attribute(bdict, 'Mass Control', weight_control == 'Mass' ? 2 : 1)
        end
        i.delete_attribute(bdict, 'Weight Control')
      end
      # Replace dynamic friction
      dynamic_friction = i.get_attribute(bdict, 'Dynamic Friction')
      if dynamic_friction
        if i.get_attribute(bdict, 'Kinetic Friction').nil?
          i.set_attribute(bdict, 'Kinetic Friction', dynamic_friction)
        end
        i.delete_attribute(bdict, 'Dynamic Friction')
      end
      # Update emitter to use seconds
      attr = i.get_attribute(bdict, 'Emitter Rate')
      i.set_attribute(bdict, 'Emitter Rate', attr.to_f * update_timestep) if attr
      attr = i.get_attribute(bdict, 'Emitter Delay')
      i.set_attribute(bdict, 'Emitter Delay', attr.to_f * update_timestep) if attr
      attr = i.get_attribute(bdict, 'Emitter Lifetime')
      i.set_attribute(bdict, 'Emitter Lifetime', attr.to_f * update_timestep) if attr
      # Update thruster lock axis to axes
      attr = i.get_attribute(bdict, 'Thruster Lock Axes')
      unless attr.nil?
        i.set_attribute(bdict, 'Thruster Lock Axes', attr)
        i.delete_attribute(bdict, 'Thruster Lock Axis')
      end
      # Update emitter lock axis to axes
      attr = i.get_attribute(bdict, 'Emitter Lock Axes')
      unless attr.nil?
        i.set_attribute(bdict, 'Emitter Lock Axes', attr)
        i.delete_attribute(bdict, 'Emitter Lock Axis')
      end
      # Replace Compound from CD shapes with default
      shape = i.get_attribute(bdict, 'Shape')
      if shape == 'Compound from CD'
        i.delete_attribute(bdict, 'Shape')
        shape = nil
      end
      # Replace shape with shape id to conserve size
      if shape.is_a?(String)
        found = false
        MSPhysics::SHAPES.each { |k, v|
          if shape == v
            i.set_attribute(bdict, 'Shape', k)
            found = true
            break
          end
        }
        i.delete_attribute(bdict, 'Shape') unless found
      end
    }
  }
  # Replace exact solver with iterative 4 passes and accurate joint solver
  if model.get_attribute('MSPhysics', 'Solver Model') == 0
    model.set_attribute('MSPhysics', 'Solver Model', 4)
    unless model.get_attribute('MSPhysics', 'Joint Algorithm')
      model.set_attribute('MSPhysics', 'Joint Algorithm', 0)
    end
  end
  # Use fast joint algorithm unless set
  unless model.get_attribute('MSPhysics', 'Joint Algorithm')
    model.set_attribute('MSPhysics', 'Joint Algorithm', 2)
  end
  # End operation
  model.commit_operation if wrap_op
end

.newton_float_sizeInteger

Get float size of the Newton Dynamics physics SDK.

Returns:

  • (Integer)

Since:

  • 1.0.0


466
467
468
# File 'RubyExtension/MSPhysics/main.rb', line 466

def newton_float_size
  MSPhysics::Newton.get_float_size
end

.newton_memory_usedInteger

Get memory used by the Newton Dynamics physics SDK at the current time.

Returns:

  • (Integer)

Since:

  • 1.0.0


472
473
474
# File 'RubyExtension/MSPhysics/main.rb', line 472

def newton_memory_used
  MSPhysics::Newton.get_memory_used
end

.newton_versionString

Get version of the Newton Dynamics physics SDK.

Returns:

  • (String)

Since:

  • 1.0.0


460
461
462
# File 'RubyExtension/MSPhysics/main.rb', line 460

def newton_version
  MSPhysics::Newton.get_version
end

.set_attribute(ents, handle, name, value) ⇒ void

Note:

Manually wrap the operation.

This method returns an undefined value.

Assign attribute value to a collection of entities.

Parameters:

  • ents (Array<Sketchup::Entity>)

    A collection of entities.

  • handle (String)

    Dictionary name.

  • name (String)

    Attribute name.

  • value (Object)

    Attribute value.

Since:

  • 1.0.0


381
382
383
384
385
# File 'RubyExtension/MSPhysics/main.rb', line 381

def set_attribute(ents, handle, name, value)
  ents.each { |e|
    e.set_attribute(handle, name, value)
  }
end

.set_joint_scale(scale, wrap_op = true) ⇒ Numeric

Set physical joint scale.

Parameters:

  • scale (Numeric)

    A value between 0.01 and 100.00

  • wrap_op (Boolean) (defaults to: true)

    Whether to wrap in operation.

Returns:

  • (Numeric)

Since:

  • 1.0.0


445
446
447
448
449
450
451
452
453
454
455
456
# File 'RubyExtension/MSPhysics/main.rb', line 445

def set_joint_scale(scale, wrap_op = true)
  scale = AMS.clamp(scale.to_f, 0.01, 100.00)
  model = Sketchup.active_model
  if wrap_op
    op = 'MSPhysics - Scale Joints'
    Sketchup.version.to_i > 6 ? model.start_operation(op, true, false, false) : model.start_operation(op)
  end
  model.set_attribute('MSPhysics', 'Joint Scale', scale)
  count = scale_joints(scale)
  model.commit_operation if wrap_op
  count
end

.verify_version(wrap_op = true) ⇒ Boolean

Displays MSPhysics version text.

Parameters:

  • wrap_op (Boolean) (defaults to: true)

    Whether to wrap in operation.

Returns:

  • (Boolean)

    Whether the user chose to continue running.

Since:

  • 1.0.0


561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
# File 'RubyExtension/MSPhysics/main.rb', line 561

def verify_version(wrap_op = true)
  model = Sketchup.active_model
  mvers = model.get_attribute('MSPhysics', 'Version')
  cvers = MSPhysics::VERSION
  cver = cvers.gsub(/\./, '').to_i
  bmake_compatible = false
  if mvers.is_a?(String)
    mver = mvers.gsub(/\./, '').to_i
    if mver == cver
      return true
    elsif mver < cver
      bmake_compatible = true
    elsif mver > cver
      return false if ::UI.messagebox("This model was created with MSPhysics #{mvers}. Your version is #{cvers}. Using an outdated version may result in an improper behaviour! Would you like to continue?", MB_YESNO) == IDNO
    end
  end
  te = nil
  model.entities.each { |e|
    if e.is_a?(Sketchup::Text) && e.get_attribute('MSPhysics', 'Name') == 'Version Text'
      te = e
      break
    end
  }
  if wrap_op
    op = 'MSPhysics - Utilizing Version'
    Sketchup.version.to_i > 6 ? model.start_operation(op, true, false, false) : model.start_operation(op)
  end
  make_compatible(false) if bmake_compatible
  if te
    te.set_text("Created with MSPhysics #{cvers}\n#{te.text}")
  else
    te = add_watermark_text(10, 10, "Created with MSPhysics #{cvers}", 'Version Text')
  end
  model.set_attribute('MSPhysics', 'Version', cvers)
  model.commit_operation if wrap_op
  true
end