Compare commits

...

3 Commits

Author SHA1 Message Date
teverse 2f894740e0 history wip 2019-12-16 21:51:08 +00:00
teverse 9646955c60 add clipboard, finish hand tool 2019-12-16 21:08:36 +00:00
Jay 99a26c634e Hand tool 2019-12-15 20:53:53 +00:00
8 changed files with 145 additions and 17 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

View File

@ -0,0 +1,76 @@
local keybinder = require("tevgit:workshop/controllers/core/keybinder.lua")
local history = require("tevgit:workshop/controllers/core/history.lua")
local selection = require("tevgit:workshop/controllers/core/selection.lua")
local clipboard = {}
keybinder:bind({
name = "copy",
key = enums.key.c,
priorKey = enums.key.leftCtrl,
action = function()
clipboard = selection.selection
end
})
keybinder:bind({
name = "paste",
key = enums.key.v,
priorKey = enums.key.leftCtrl,
action = function()
history.beginAction(workspace, "Paste")
local bounds = aabb()
if #clipboard > 0 then
bounds.min = clipboard[1].position
bounds.max = clipboard[1].position
end
-- translates the pasted objects by:
local offset = vector3(0, 0, 0)
-- pass the clipboard to calculate bounds
for _,v in pairs(clipboard) do
if type(v.position) == "vector3" and type(v.size) == "vector3" then
bounds:expand(v.position + (v.size / 2))
bounds:expand(v.position - (v.size / 2))
end
end
offset = vector3(0, bounds.max.y - bounds.min.y, 0)
local centre = bounds:getCentre()
local clones = {}
for _,v in pairs(clipboard) do
if v and v.alive then
local new = v:clone()
new.parent = workspace
if type(new.position) == "vector3" then
new.position = new.position + offset
end
table.insert(clones, new)
end
end
history.endAction()
selection.setSelection(clones)
end
})
keybinder:bind({
name = "duplicate",
key = enums.key.d,
priorKey = enums.key.leftCtrl,
action = function()
history.beginAction(workspace, "Duplicate")
local clones = {}
for _,v in pairs(selection.selection) do
if v and v.alive then
local new = v:clone()
new.parent = workspace
table.insert(clones, new)
end
end
history.endAction()
selection.setSelection(clones)
end
})

View File

@ -53,12 +53,11 @@ local function destroyingListener()
if not changes[changedObject] then
changes[changedObject] = {}
end
-- Object is being destroyed, let's save a copy of all their writable properties so the user can undo this action
local members = workshop:getMembersOfObject( changedObject )
local members = shared.workshop:getMembersOfObject( changedObject )
local toStore = {}
for _, prop in pairs(members) do
local val = object[prop.property]
local val = changedObject[prop.property]
local pType = type(val)
if prop.writable and pType ~= "function" then
@ -66,7 +65,9 @@ local function destroyingListener()
toStore[prop.property] = val
end
end
toStore["parent"] = changedObject.parent
toStore["className"] = changedObject.className
table.insert(destroyedObjects, toStore)
end
@ -98,13 +99,13 @@ local function beginAction( object, name )
if type(object) == "table" then
for _,v in pairs(object) do
table.insert(eventListeners, v:onSync("changed", changedListener))
table.insert(eventListeners, v:onSync("destroying", destroyingListener))
table.insert(eventListeners, v:onSync("childAdded", ChildAddedListener))
table.insert(eventListeners, v:onSync("destroying", destroyingListener))
end
else
table.insert(eventListeners, object:onSync("changed", changedListener))
table.insert(eventListeners, object:onSync("destroying", destroyingListener))
table.insert(eventListeners, object:onSync("childAdded", ChildAddedListener))
table.insert(eventListeners, object:onSync("destroying", destroyingListener))
end
end
@ -139,6 +140,15 @@ end
local function undo()
if actions[pointer] ~= nil then
-- destroyed objects (restore)
for _, properties in pairs(actions[pointer][4]) do
local obj = engine[properties["className"]]()
for property, value in pairs(properties) do
obj[property] = value
end
end
for object, properties in pairs(actions[pointer][3]) do
if object and object.alive then
for property, values in pairs(properties) do
@ -147,7 +157,8 @@ local function undo()
object[property] = values[1]
end
else
warn("need to put logic here")
for k,v in pairs(properties) do print(k,v) end
warn("There was a change recorded, but we couldn't find the object.")
end
end
@ -165,10 +176,14 @@ local function redo()
if actions[pointer + 1] ~= nil then
pointer = pointer + 1
for object, properties in pairs(actions[pointer][3]) do
for property, values in pairs(properties) do
--values[1] = original value
--values[2] = changed value
object[property] = values[2]
if object and object.alive then
for property, values in pairs(properties) do
--values[1] = original value
--values[2] = changed value
object[property] = values[2]
end
else
warn("There was a change recorded, but we couldn't find the object.")
end
end

View File

@ -34,7 +34,12 @@ function hotkeysController:handle(inputObject)
end
end
end
else
end
end
-- bad: seperate pass because we prioritise prior key commands.
for key, data in pairs(self.bindings) do
if (data.action) then
if (inputObject.key == key) then
data.action()
return

View File

@ -11,7 +11,9 @@ local ui = require("tevgit:workshop/controllers/ui/core/ui.lua")
local shared = require("tevgit:workshop/controllers/shared.lua")
local clickEvent = nil
local keyEvent = nil
local settingsGui = nil
local isDragging = false
return {
name = toolName,
@ -52,6 +54,19 @@ return {
gridStep = tonumber(gridStepInput.text) or 0
end)
local offsets = {}
keyEvent = engine.input:keyPressed(function( inputObj )
if inputObj.key == enums.key.r and isDragging then
local targetRot = quaternion:setEuler(0,math.rad(-45),0)
for _,v in pairs(selection.selection) do
if offsets[v] then
offsets[v][2] = offsets[v][2] * targetRot
v.rotation = offsets[v][2]
end
end
end
end)
-- Set the event listener to a variable so we can disconnect this handler
-- when the tool is deactivated
clickEvent = engine.input:mouseLeftPressed(function ( inputObj )
@ -84,9 +99,12 @@ return {
local mouseOffset = hit.hitPosition - centre
-- calculate every selected item's offset from the centre
local offsets = {}
offsets = {}
for _,v in pairs(selection.selection) do
offsets[v] = v.position - centre
--offsets[v] = v.position - centre
local relative = quaternion(0, 0, 0, 1) * v.rotation;
local positionOffset = (relative*quaternion(0, 0, 0, 1)):inverse() * (v.position - centre)
offsets[v] = {positionOffset, relative}
end
-- tell history to monitor changes we make to selected items
@ -99,6 +117,8 @@ return {
rotation = quaternion:setEuler(math.rad(90), 0, 0)
})
isDragging = true
while engine.input:isMouseButtonDown(enums.mouseButton.left) do
-- fire a ray, exclude selected items.
local hits, didExclude = engine.physics:rayTestScreenAllHits(engine.input.mousePosition, selection.selection)
@ -111,7 +131,9 @@ return {
local minY = hits[1].hitPosition.y
for _,v in pairs(selection.selection) do
if offsets[v] then
v.position = newCentre + offsets[v]
v.position = newCentre + (offsets[v][2] * offsets[v][1])
-- Calculate the lowest point in the selection:
local size = v.size or vector3(0,0,0)
minY = math.min(minY, v.position.y - (size.y/2))
avgPos = avgPos + v.position
@ -135,6 +157,8 @@ return {
wait()
end
isDragging = false
history.endAction()
grid:destroy()
@ -161,6 +185,11 @@ return {
settingsGui = nil
end
if keyEvent then
keyEvent:disconnect()
keyEvent = nil
end
if clickEvent then
clickEvent:disconnect()
clickEvent = nil

View File

@ -50,7 +50,7 @@ local function draw()
ui.create("guiTextBox", window.content, {
size = guiCoord(1, 0, 0, 18),
position = guiCoord(0, 0, 0, yPos),
text = string.format("[ %s ] %s (change: %i, add: %i, rem: %i)", formattedDate, actionName, history.count(action[3]), history.count(action[4]), history.count(action[5]))
text = string.format("[ %s ] %s (change: %i, add: %i, rem: %i)", formattedDate, actionName, history.count(action[3]), #action[4], #action[5])
}, "backgroundText")
yPos = yPos + 20

View File

@ -196,7 +196,7 @@ createInputs = {
backgroundAlpha = 0.25,
readOnly = false,
multiline = false,
wrapped = true,
wrap = true,
fontSize = 18,
name = "input",
size = guiCoord(1, -4, 0, 18),

View File

@ -69,7 +69,9 @@ local function beginLoad(workshop)
-- Okay now we can load remote files whilst the user is looking at a loading screen.
shared.controllers.env = require("tevgit:workshop/controllers/environment/main.lua")
shared.controllers.history = require("tevgit:workshop/controllers/core/history.lua")
shared.controllers.history = require("tevgit:workshop/controllers/core/history.lua")
shared.controllers.clipboard = require("tevgit:workshop/controllers/core/clipboard.lua")
-- Create the Teverse interface
require("tevgit:workshop/controllers/ui/createInterface.lua")