mirror of https://github.com/teverse/teverse
244 lines
7.4 KiB
Lua
244 lines
7.4 KiB
Lua
--[[
|
|
Copyright 2019 Teverse
|
|
@File move.lua
|
|
@Author(s) Jay
|
|
--]]
|
|
|
|
TOOL_NAME = "Move"
|
|
TOOL_ICON = "fa:s-arrows-alt"
|
|
TOOL_DESCRIPTION = "Use this to move primitives along an axis."
|
|
|
|
local toolsController = require("tevgit:create/controllers/tool.lua")
|
|
local selectionController = require("tevgit:create/controllers/select.lua")
|
|
local toolSettings = require("tevgit:create/controllers/toolSettings.lua")
|
|
local helpers = require("tevgit:create/helpers.lua")
|
|
local history = require("tevgit:create/controllers/history.lua")
|
|
|
|
local mouseUpEvent
|
|
|
|
local function onToolActivated(toolId)
|
|
-- This is used to raycast the user's mouse position to an axis
|
|
local gridGuideline = engine.construct("block", workspace, {
|
|
size = vector3(0,0,0),
|
|
colour = colour(1,1,1),
|
|
opacity = 0,
|
|
workshopLocked = true,
|
|
castsShadows = false
|
|
})
|
|
|
|
toolsController.tools[toolId].data.gridGuideline = gridGuideline
|
|
|
|
-- TODO: Refactor code from old create mode...
|
|
-- Everything is essentially the same, apart from UI needs to use the ui controller
|
|
-- And also: engine.construct should be used throughout.
|
|
|
|
toolsController.tools[toolId].data.handles = {}
|
|
local components = {"x", "y", "z"}
|
|
local c = 1
|
|
local o = 0
|
|
|
|
local leftButtonDown = false
|
|
|
|
-- For history and adding undo points.
|
|
local originalPositions = {}
|
|
|
|
-- Probably can be improved
|
|
-- Creates two 'handles' for each axis.
|
|
-- Should work on all selected items.
|
|
|
|
for i = 1,6 do
|
|
local component = components[c]
|
|
local face = vector3(0,0,0)
|
|
face[component] = o == 0 and o-1 or o
|
|
local thisC = c
|
|
|
|
local handle = engine.construct("block", nil, {
|
|
name = "_CreateMode_",
|
|
castsShadows = false,
|
|
opacity = 0,
|
|
renderQueue=1,
|
|
doNotSerialise=true,
|
|
size = vector3(0.1, 0.1, 0.1),
|
|
colour = colour(c==1 and 1 or 0, c==2 and 1 or 0, c==3 and 1 or 0),
|
|
emissiveColour = colour(c==1 and .8 or 0, c==2 and .8 or 0, c==3 and .8 or 0),
|
|
workshopLocked = true,
|
|
mesh = "primitive:cone"
|
|
})
|
|
|
|
|
|
|
|
handle:mouseLeftPressed(function()
|
|
print("clicked")
|
|
if leftButtonDown then return end -- how
|
|
print("continued")
|
|
leftButtonDown = handle
|
|
|
|
selectionController.selectable = false
|
|
gridGuideline.size = vector3(300, 0.1, 300)
|
|
gridGuideline.rotation = handle.rotation
|
|
gridGuideline.position = handle.position
|
|
if component == "x" then
|
|
gridGuideline.rotation = gridGuideline.rotation * quaternion():setEuler(math.rad(-45),math.rad(-45),0)
|
|
end
|
|
|
|
local mouseHit = engine.physics:rayTestScreen( engine.input.mousePosition )
|
|
if not mouseHit or not mouseHit.object == gridGuideline then
|
|
return print("Error, couldn't cast ray to guideline.")
|
|
end
|
|
|
|
local mouseoffsets = {}
|
|
originalPositions = {}
|
|
for _,v in pairs(selectionController.selection) do
|
|
mouseoffsets[v] = (mouseHit.hitPosition - v.position)
|
|
originalPositions[v] = v.position
|
|
end
|
|
|
|
local lastHit = mouseHit.hitPosition
|
|
|
|
local gridStep = toolSettings.gridStep
|
|
-- IM CURRENTLY THINKING
|
|
-- Add special hook function to history.lua for only accepting values with intervals (needed for move & resize, maybe rotate)
|
|
-- and it gets the difference between two values
|
|
|
|
-- OR: Detect when mouse released from marker and then store that value. Add it to history if pos if updated again?
|
|
-- This could use lastHit or something similar?
|
|
repeat
|
|
if toolsController.currentToolId == toolId then
|
|
--Face camera on one Axis
|
|
gridGuideline.position = handle.position
|
|
if component == "x" then
|
|
local xVector1 = vector3(0, gridGuideline.position.y,gridGuideline.position.z)
|
|
local xVector2 = vector3(0, workspace.camera.position.y, workspace.camera.position.z)
|
|
|
|
local lookAt = gridGuideline.rotation:setLookRotation( xVector1 - xVector2 )
|
|
gridGuideline.rotation = lookAt * quaternion():setEuler(math.rad(45),0,0)
|
|
else
|
|
local pos1 = gridGuideline.position
|
|
pos1[component] = 0
|
|
|
|
local pos2 = workspace.camera.position
|
|
pos2[component] = 0
|
|
|
|
local lookAt = gridGuideline.rotation:setLookRotation( pos1 - pos2 )
|
|
gridGuideline.rotation = lookAt * quaternion():setEuler(math.rad(45),0,0)
|
|
end
|
|
|
|
local mouseHits = engine.physics:rayTestScreenAllHits( engine.input.mousePosition )
|
|
local mouseHit = nil
|
|
-- We only want the gridGuideline
|
|
for _,hit in pairs(mouseHits) do
|
|
if hit.object == gridGuideline then
|
|
mouseHit = hit
|
|
goto skip_loop
|
|
end
|
|
end
|
|
::skip_loop::
|
|
|
|
if mouseHit and mouseHit.object == gridGuideline and lastHit ~= mouseHit.hitPosition then
|
|
local target = mouseHit.hitPosition
|
|
lastHit = target
|
|
|
|
for _,v in pairs(selectionController.selection) do
|
|
if mouseoffsets[v] then
|
|
local newPos = target - mouseoffsets[v]
|
|
local pos = v.position
|
|
if gridStep > 0 and toolSettings.axis[thisC][2] then
|
|
pos[component] = helpers.roundToMultiple(newPos[component], gridStep)
|
|
else
|
|
pos[component] = newPos[component]
|
|
end
|
|
|
|
v.position = pos
|
|
--engine.tween:begin(v, .05, {position = pos}, "inOutQuad")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
wait()
|
|
until not leftButtonDown or not toolsController.currentToolId == toolId
|
|
|
|
delay(function() if not leftButtonDown then selectionController.selectable = true end end, 0.3)
|
|
|
|
if toolsController.currentToolId == toolId then
|
|
gridGuideline.size = vector3(0,0,0)
|
|
end
|
|
end)
|
|
|
|
table.insert(toolsController.tools[toolId].data.handles, {handle, face})
|
|
|
|
if i % 2 == 0 then
|
|
c=c+1
|
|
o = 0
|
|
else
|
|
o = o + 1
|
|
end
|
|
end
|
|
|
|
mouseUpEvent = engine.input:mouseLeftReleased(function()
|
|
leftButtonDown = false
|
|
if originalPositions then
|
|
for item, pos in pairs(originalPositions) do
|
|
history.addPoint(item, "position", pos)
|
|
end
|
|
end
|
|
|
|
|
|
end)
|
|
|
|
updateHandles = function()
|
|
if selectionController.boundingBox.size == vector3(0,0,0) then
|
|
for _,v in pairs(toolsController.tools[toolId].data.handles) do
|
|
v[1].size = vector3(0,0,0)
|
|
v[1].opacity = 0
|
|
end
|
|
else
|
|
for _,v in pairs(toolsController.tools[toolId].data.handles) do
|
|
v[1].position = selectionController.boundingBox.position + selectionController.boundingBox.rotation* ((v[2] * selectionController.boundingBox.size/2) + (v[2]*1.5))
|
|
v[1]:lookAt(selectionController.boundingBox.position)
|
|
v[1].rotation = v[1].rotation * quaternion():setEuler(math.rad(90),0,0)
|
|
v[1].size = vector3(0.2, 0.4, 0.2)
|
|
v[1].opacity = 1
|
|
end
|
|
end
|
|
end
|
|
|
|
toolsController.tools[toolId].data.keyDownEvent = engine.input:keyPressed(function ( inp )
|
|
if inp.key == enums.key.t then
|
|
--inputGrid.text = "0"
|
|
end
|
|
end)
|
|
|
|
toolsController.tools[toolId].data.boundingEvent = selectionController.boundingBox:changed(updateHandles)
|
|
updateHandles()
|
|
end
|
|
|
|
local function onToolDeactivated(toolId)
|
|
toolsController.tools[toolId].data.gridGuideline:destroy()
|
|
toolsController.tools[toolId].data.gridGuideline = nil
|
|
|
|
for _,v in pairs(toolsController.tools[toolId].data.handles) do
|
|
v[1]:destroy()
|
|
end
|
|
toolsController.tools[toolId].data.handles = nil
|
|
|
|
toolsController.tools[toolId].data.boundingEvent:disconnect()
|
|
toolsController.tools[toolId].data.boundingEvent = nil
|
|
|
|
if mouseUpEvent then
|
|
mouseUpEvent:disconnect()
|
|
mouseUpEvent = nil
|
|
end
|
|
end
|
|
|
|
return toolsController:register({
|
|
|
|
name = TOOL_NAME,
|
|
icon = TOOL_ICON,
|
|
description = TOOL_DESCRIPTION,
|
|
|
|
hotKey = enums.key.number3,
|
|
|
|
activated = onToolActivated,
|
|
deactivated = onToolDeactivated
|
|
|
|
}) |