I was starting to make a wall plugin, but I’m having a lot of trouble figuring out how to create a preview of the drawing.
Why is the preview disappearing depending on the zoom?
Is there a better way to do this?
I just want to click, choose height and thickness, and then draw the wall, seeing a preview of how it will look as I draw.
Note: Is it possible to lock the axes while drawing? And click on other points, like an imported dwg?
module ExemploWallTool
extend self
class WallTool
def initialize(params)
@params = params
@points = []
@mouse_point = nil
@drawing = false
end
def onLButtonDown(flags, x, y, view)
ip = view.inputpoint(x, y)
point_clicked = ip.position
if !@drawing
@points = [point_clicked]
@drawing = true
else
@points << point_clicked
end
view.invalidate
end
def onLButtonDoubleClick(flags, x, y, view)
if @drawing
@drawing = false
create_wall_geometry
@points.clear
view.invalidate
end
end
def onMouseMove(flags, x, y, view)
if @drawing
ip = view.inputpoint(x, y)
@mouse_point = ip.position
view.invalidate
end
end
# ----------------------------
def draw(view)
return unless @drawing
return if @points.empty?
wall_width = @params["Wall Width"].to_f
view.drawing_color = "yellow"
view.line_width = 1
points_to_draw = @points.clone
points_to_draw << @mouse_point if @mouse_point
(points_to_draw.size - 1).times do |i|
pt1 = points_to_draw[i]
pt2 = points_to_draw[i + 1]
vec = pt2 - pt1
next if vec.length == 0
vec.normalize!
perp = Geom::Vector3d.new(-vec.y, vec.x, 0)
next if perp.length == 0
perp.length = wall_width / 2.0
p1 = pt1.offset(perp)
p2 = pt2.offset(perp)
p3 = pt2.offset(perp.reverse)
p4 = pt1.offset(perp.reverse)
view.draw(GL_LINE_LOOP, [p1, p2, p3, p4])
end
end
# ----------------------------
def create_wall_geometry
model = Sketchup.active_model
ents = model.active_entities
return if @points.size < 2
wall_width = @params["Wall Width"].to_f
wall_height = @params["Wall Height"].to_f
model.start_operation("Criar Parede", true)
begin
wall_group = ents.add_group
group_ents = wall_group.entities
path_edges = group_ents.add_edges(@points)
cross_pts = []
half_w = wall_width / 2.0
cross_pts << Geom::Point3d.new(-half_w, 0, 0)
cross_pts << Geom::Point3d.new( half_w, 0, 0)
cross_pts << Geom::Point3d.new( half_w, 0, wall_height)
cross_pts << Geom::Point3d.new(-half_w, 0, wall_height)
face = group_ents.add_face(cross_pts)
face.reverse! if face.normal.y > 0
first_segment = @points[1] - @points[0]
first_segment.normalize!
neg_y = Geom::Vector3d.new(0, -1, 0)
angle = neg_y.angle_between(first_segment)
axis = neg_y * first_segment
if axis.length > 0
axis.normalize!
rot = Geom::Transformation.rotation(ORIGIN, axis, angle)
group_ents.transform_entities(rot, face)
end
move_to_first = Geom::Transformation.translation(@points[0] - ORIGIN)
group_ents.transform_entities(move_to_first, face)
face.followme(path_edges)
path_edges.each(&:erase!)
rescue => e
puts "Erro ao criar parede: #{e.message}"
ensure
model.commit_operation
end
end
end
# ----------------------------
def ativar_ferramenta_parede
prompts = ["Wall Width", "Wall Height"]
defaults = [15.0, 300.0]
list = ["", ""]
input = UI.inputbox(prompts, defaults, list, "Wall Configurations")
return unless input
params = {
"Wall Width" => input[0],
"Wall Height" => input[1]
}
Sketchup.active_model.select_tool(WallTool.new(params))
end
unless file_loaded?(__FILE__)
menu = UI.menu("Plugins")
menu.add_item("Wall Preview") {
ativar_ferramenta_parede
}
file_loaded(__FILE__)
end
end