/tools/jselect.lua
Lua | 206 lines | 183 code | 17 blank | 6 comment | 37 complexity | 5085b14b11d616ac4fc74875fb8a7475 MD5 | raw file
- --
- -- Selects joints
- --
- JSelectTool = {}
- JSelectToolMT = { __index = JSelectTool }
- setmetatable(JSelectTool, { __index = Tool })
- function JSelectTool:Create(owner)
- local self = Tool:Create(owner, JSelectToolMT)
- return self
- end
- function JSelectTool:Destroy()
- Tool.Destroy(self)
- end
- function JSelectTool:MousePress(wx, wy, alt, shift, ctrl)
- local owner = self.owner
- local gstate = owner.gstate
- local scene = owner:get_scene()
- local selection = gstate.selection
- local selection2 = gstate.selection2
- local z = scene:GetZoom()
- local j, b = gstate:QueryAnchors(selection2, wx, wy, 5*z)
- if #j > 0 then
- owner:set_tool(AnchorTool, wx, wy, j[1], b[1])
- return
- end
- local q, j = gstate:QueryJoints(wx, wy, wx, wy, 5*z)
- if #q > 0 and alt == false and shift == false then
- local i = table.find(selection, q[1])
- if i then
- gstate:ShiftSelection(i, 1)
- else
- gstate:ClearSelection()
- gstate:AddToSelection({ q[1] }, { j[1] })
- end
- owner:set_tool(JTranslateTool, selection, selection2)
- owner.tool:MousePress(wx, wy, alt, shift)
- else
- self.alt, self.shift = alt, shift
- self.sx, self.sy = wx, wy
- if alt == true or shift == true then
- self.oldselect = { unpack(gstate.selection) }
- self.oldselect2 = { unpack(gstate.selection2) }
- else
- gstate:ClearSelection()
- end
- end
- end
- function JSelectTool:MouseMove(wx, wy, owx, owy)
- local sx, sy = self.sx, self.sy
- if sx == nil or sy == nil then
- return
- end
- local scene = self.owner:get_scene()
- local gstate = self.owner.gstate
- self.ex, self.ey = wx, wy
- local z = scene:GetZoom()
- local q, s = gstate:QueryJoints(sx, sy, wx, wy, z*4)
- gstate:ClearSelection()
- if self.oldselect then
- gstate:AddToSelection(self.oldselect, self.oldselect2)
- end
- if self.alt == true then
- gstate:RemoveFromSelection(q, s)
- else
- gstate:AddToSelection(q, s)
- end
- end
- function JSelectTool:MouseRelease(wx, wy)
- self:MouseMove(wx, wy, wx, wy)
- self.alt, self.shift = nil, nil
- self.sx, self.sy = nil, nil
- self.ex, self.ey = nil, nil
- self.oldselect = nil
- self.oldselect2 = nil
- end
- function JSelectTool:Redraw(dt)
- local owner = self.owner
- local gstate = owner.gstate
- local scene = owner:get_scene()
- local camera = owner:get_camera()
- if self.ex and self.ey then
- local sx, sy = self.sx, self.sy
- local ex, ey = self.ex, self.ey
- scene:DrawLine(sx, sy, sx, ey, 1, WHITE, 1)
- scene:DrawLine(sx, ey, ex, ey, 1, WHITE, 1)
- scene:DrawLine(ex, ey, ex, sy, 1, WHITE, 1)
- scene:DrawLine(ex, sy, sx, sy, 1, WHITE, 1)
- scene:DrawStatus("Selecting joints (shift/alt to modify)")
- return
- end
-
- self:RedrawAnchors()
-
- local z = scene:GetZoom()
- local mx, my = mouse.xaxis, mouse.yaxis
- local wx, wy = camera:get_world_point(mx, my)
- if #gstate.selection > 0 then
- local f = "%d joint controls selected"
- local sz = string.format(f, #gstate.selection)
- scene:DrawStatus(sz)
- local j, b = gstate:QueryAnchors(gstate.selection2, wx, wy, 4*z)
- if #j > 0 then
- local f = "Anchor\n body:%d "
- local sz = string.format(f, b[1].id)
- scene:DrawTooltip(sz, wx, wy)
- end
- else
- scene:DrawStatus("Edit joints")
-
- local v, j = gstate:QueryJoints(wx, wy, wx, wy, 4*z)
- v = v[1]
- j = j[1]
- if v then
- local t = j:GetType()
- local sz
- if t == 'revolute' then
- if j:IsLimitEnabled() then
- local l = j:GetLowerLimit()
- local u = j:GetUpperLimit()
- sz = string.format("\n limits:%g, %g ", l, u)
- end
- elseif t == 'distance' then
- local len = j.def.length
- sz = string.format("\n length:%g ", len)
- elseif t == 'rope' then
- local len = j.def.maxLength
- sz = string.format("\n maxLength:%g ", len)
- elseif t == 'prismatic' then
- local ax, ay = j:GetWorldAxis()
- sz = string.format("\n axis:%g, %g", ax, ay)
- if j:IsLimitEnabled() then
- local l = j:GetLowerLimit()
- local u = j:GetUpperLimit()
- sz = sz .. string.format(" \n limits:%g, %g ", l, u)
- end
- elseif t == 'gear' then
- local j1 = j:GetJoint1().id
- local j2 = j:GetJoint2().id
- sz = string.format("\n joint1:%g \n joint2:%g", j1, j2)
- end
- sz = sz or ""
- local x, y = j.def.body1:GetWorldPoint(v.x, v.y)
- local cc = "false"
- if j.def.collideConnected == true then
- cc = "true"
- end
- local f = "Joint \n id:%d \n type:%s \n x:%g \n y:%g \n body1:%d \n body2:%d \n collideconnected: %s %s "
- local sz = string.format(f, j.id, t, x, y, j.def.body1.id, j.def.body2.id, cc, sz)
- scene:DrawTooltip(sz, wx, wy)
- end
- end
- end
- function JSelectTool:RedrawAnchors()
- local owner = self.owner
- local world = owner:get_world()
- local scene = owner:get_scene()
- local gstate = owner.gstate
- for i, anchor in ipairs(gstate.selection) do
- local joint = gstate.selection2[i]
- local b1, b2 = joint.def.body1, joint.def.body2
- if anchor == joint.def.localAnchor2 then
- b1, b2 = b2, b1
- end
- local wvx, wvy = anchor.x, anchor.y
- if anchor == joint.def.localAnchor1 or anchor == joint.def.localAnchor2 then
- wvx, wvy = b1:GetWorldPoint(anchor.x, anchor.y)
- end
- -- draw lines from the joint to the attached bodies
- local cm1x, cm1y = b1:GetWorldCenter()
- local z = scene:GetZoom()
- local dx, dy = (cm1x - wvx)/2, (cm1y - wvy)/2
- local cx, cy = wvx + dx, wvy + dy
- scene:DrawLine(wvx, wvy, cm1x, cm1y, 1, DARKORANGE, 1)
- --scene:DrawLine(cx, cy, cx + dy, cy - dx, 1, RED, 1)
- --scene:DrawCurve(wvx, wvy, cm1x, cm1y, cx + dy, cy - dx, 1, DARKORANGE, 1)
- scene:DrawImage("circle", cm1x, cm1y)
- local ox, oy = -9*z, -9*z
- local a, b = 1, 2
- if anchor == joint.def.localAnchor2 then
- ox = -ox
- a, b = b, a
- end
- scene:DrawImage("anchor" .. a, cm1x + ox, cm1y + oy)
- local type = joint:GetType()
- if type ~= 'distance' and type ~= 'prismatic' and type ~= 'rope' then
- local cm2x, cm2y = b2:GetWorldCenter()
- scene:DrawLine(wvx, wvy, cm2x, cm2y, 1, DARKORANGE, 1)
- scene:DrawImage("circle", cm2x, cm2y)
- scene:DrawImage("anchor" .. b, cm2x - ox, cm2y + oy)
- end
- end
- end