mirror of https://github.com/teverse/teverse
Compare commits
2 Commits
b688f4a49d
...
a4dc190998
Author | SHA1 | Date |
---|---|---|
teverse | a4dc190998 | |
teverse | e6528bdc2a |
|
@ -1,83 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- camera.lua
|
||||
|
||||
local cameraController = {}
|
||||
local selectionController = require("tevgit:create/controllers/select.lua")
|
||||
|
||||
cameraController.zoomStep = 3
|
||||
cameraController.rotateStep = 0.003
|
||||
cameraController.moveStep = 0.5 -- how fast the camera moves
|
||||
|
||||
cameraController.camera = workspace.camera
|
||||
|
||||
-- Setup the initial position of the camera
|
||||
cameraController.camera.position = vector3(11, 5, 10)
|
||||
cameraController.camera:lookAt(vector3(0,0,0))
|
||||
-- Camera key input values
|
||||
cameraController.cameraKeyEventLooping = false
|
||||
cameraController.cameraKeyArray = {
|
||||
[enums.key.w] = vector3(0, 0, 1),
|
||||
[enums.key.s] = vector3(0, 0, -1),
|
||||
[enums.key.a] = vector3(-1, 0, 0),
|
||||
[enums.key.d] = vector3(1, 0, 0),
|
||||
[enums.key.q] = vector3(0, -1, 0),
|
||||
[enums.key.e] = vector3(0, 1, 0)
|
||||
}
|
||||
|
||||
engine.input:mouseScrolled(function( input )
|
||||
if input.systemHandled then return end
|
||||
|
||||
local cameraPos = cameraController.camera.position
|
||||
cameraPos = cameraPos + (cameraController.camera.rotation * (cameraController.cameraKeyArray[enums.key.w] * input.movement.y * cameraController.zoomStep))
|
||||
cameraController.camera.position = cameraPos
|
||||
|
||||
end)
|
||||
|
||||
engine.input:mouseMoved(function( input )
|
||||
if engine.input:isMouseButtonDown( enums.mouseButton.right ) then
|
||||
local pitch = quaternion():setEuler(input.movement.y * cameraController.rotateStep, 0, 0)
|
||||
local yaw = quaternion():setEuler(0, input.movement.x * cameraController.rotateStep, 0)
|
||||
|
||||
-- Applied seperately to avoid camera flipping on the wrong axis.
|
||||
cameraController.camera.rotation = yaw * cameraController.camera.rotation;
|
||||
cameraController.camera.rotation = cameraController.camera.rotation * pitch
|
||||
|
||||
--updatePosition()
|
||||
end
|
||||
end)
|
||||
|
||||
engine.input:keyPressed(function( inputObj )
|
||||
if inputObj.systemHandled or engine.input:isKeyDown(enums.key.leftCtrl) then return end
|
||||
|
||||
if cameraController.cameraKeyArray[inputObj.key] and not cameraController.cameraKeyEventLooping then
|
||||
cameraController.cameraKeyEventLooping = true
|
||||
repeat
|
||||
local cameraPos = cameraController.camera.position
|
||||
|
||||
for key, vector in pairs(cameraController.cameraKeyArray) do
|
||||
-- check this key is pressed (still)
|
||||
if engine.input:isKeyDown(key) then
|
||||
cameraPos = cameraPos + (cameraController.camera.rotation * vector * cameraController.moveStep)
|
||||
end
|
||||
end
|
||||
|
||||
cameraController.cameraKeyEventLooping = (cameraPos ~= cameraController.camera.position)
|
||||
cameraController.camera.position = cameraPos
|
||||
|
||||
wait(0.001)
|
||||
|
||||
until not cameraController.cameraKeyEventLooping
|
||||
end
|
||||
|
||||
-- SELECTION SYSTEM REQUIRED
|
||||
--[[
|
||||
if inputObj.key == enums.key.f and #selectionController.selection>0 then
|
||||
local mdn = vector3(median(selectionController.selection, "x"), median(selectionController.selection, "y"),median(selectionController.selection, "z") )
|
||||
--camera.position = mdn + (camera.rotation * vector3(0,0,1) * 15)
|
||||
--print(mdn)
|
||||
engine.tween:begin(cameraController.camera, .2, {position = mdn + (cameraController.camera.rotation * vector3(0,0,1) * 15)}, "outQuad")
|
||||
end]]
|
||||
end)
|
||||
|
||||
|
||||
return cameraController
|
|
@ -1,163 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- console.lua
|
||||
-- Author(s) joritochip, TheCakeChicken
|
||||
|
||||
|
||||
|
||||
local consoleController = {}
|
||||
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
|
||||
consoleController.outputLines = {}
|
||||
|
||||
function stringSplit(inputStr, sep)
|
||||
if sep == nil then
|
||||
sep = "%s"
|
||||
end
|
||||
local t={}
|
||||
for str in string.gmatch(inputStr, "([^"..sep.."]+)") do
|
||||
table.insert(t, str)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function stringCount(inputStr, pat)
|
||||
if inputStr == nil or pat == nil then return end
|
||||
return select(2, string.gsub(inputStr, pat, ""))
|
||||
end
|
||||
|
||||
consoleController.createConsole = function(workshop)
|
||||
local windowObject = uiController.createWindow(
|
||||
workshop.interface,
|
||||
guiCoord(0.25, 0, 0.25, 0),
|
||||
guiCoord(0.5, 0, 0.5, 0),
|
||||
"Console"
|
||||
)
|
||||
|
||||
windowObject.visible = false
|
||||
consoleController.consoleObject = windowObject
|
||||
|
||||
local scrollView = uiController.create("guiScrollView", windowObject.content, {
|
||||
size = guiCoord(1, 0, 1, -25),
|
||||
position = guiCoord(0, 0, 0, 0),
|
||||
canvasSize = guiCoord(1, 0, 0, 0)
|
||||
})
|
||||
|
||||
local entryLabel = uiController.create("guiTextBox", scrollView, {
|
||||
size = guiCoord(1, -10, 0, 50),
|
||||
position = guiCoord(0, 0, 0, 0),
|
||||
name = "entryLabel",
|
||||
wrap = true,
|
||||
multiline = true,
|
||||
readOnly = true,
|
||||
align = enums.align.topLeft,
|
||||
fontSize = 20,
|
||||
textColour = colour(1, 1, 1)
|
||||
}, "default")
|
||||
|
||||
local cmdInput = uiController.create("guiFrame", windowObject.content, {
|
||||
size = guiCoord(1, 0, 0, 25),
|
||||
position = guiCoord(0, 0, 1, -25),
|
||||
name = "cmdInput"
|
||||
}, "secondary")
|
||||
|
||||
local cmdDecorText = uiController.create("guiTextBox", cmdInput, {
|
||||
size = guiCoord(0, 20, 1, 0),
|
||||
position = guiCoord(0, 5, 0, 0),
|
||||
multiline = false,
|
||||
text = ">",
|
||||
align = enums.align.middle,
|
||||
fontSize = 20,
|
||||
textColour = colour(1, 1, 1),
|
||||
name = "cmdDecorText"
|
||||
}, "secondary")
|
||||
|
||||
local cmdInputText = uiController.create("guiTextBox", cmdInput, {
|
||||
size = guiCoord(1, -30, 1, 0),
|
||||
position = guiCoord(0, 25, 0, 0),
|
||||
multiline = false,
|
||||
text = "Enter a script",
|
||||
align = enums.align.middleLeft,
|
||||
fontSize = 20,
|
||||
textColour = colour(1, 1, 1),
|
||||
name = "cmdInputText",
|
||||
readOnly = false
|
||||
}, "secondary")
|
||||
|
||||
local cmdBarActive = false
|
||||
|
||||
local commandHistoryIndex = 0
|
||||
local commandHistory = {}
|
||||
|
||||
cmdInputText:keyFocused(function()
|
||||
cmdBarActive = true
|
||||
if cmdInputText.text == "Enter a script" then cmdInputText.text = "" end
|
||||
end)
|
||||
|
||||
cmdInputText:keyUnfocused(function()
|
||||
cmdBarActive = false
|
||||
end)
|
||||
|
||||
engine.input:keyPressed(function(inputObj)
|
||||
if inputObj.key == enums.key.f12 then
|
||||
if inputObj.systemHandled then return end
|
||||
consoleController.consoleObject.visible = not consoleController.consoleObject.visible
|
||||
elseif cmdBarActive == true then
|
||||
if inputObj.key == enums.key["return"] then
|
||||
if cmdInputText.text ~= "Enter a script" and cmdInputText.text ~= "" then
|
||||
table.insert(commandHistory, cmdInputText.text)
|
||||
commandHistoryIndex = #commandHistory + 1
|
||||
|
||||
print("> "..cmdInputText.text)
|
||||
wait()
|
||||
workshop:loadString(cmdInputText.text)
|
||||
|
||||
cmdInputText.text = ""
|
||||
end
|
||||
elseif inputObj.key == enums.key.up and #commandHistory > 0 then
|
||||
if commandHistoryIndex - 1 > 0 then
|
||||
commandHistoryIndex = commandHistoryIndex - 1
|
||||
cmdInputText.text = commandHistory[commandHistoryIndex]
|
||||
end
|
||||
elseif inputObj.key == enums.key.down and #commandHistory > 0 then
|
||||
if commandHistoryIndex < #commandHistory + 1 then
|
||||
commandHistoryIndex = commandHistoryIndex + 1
|
||||
if commandHistoryIndex > #commandHistory then
|
||||
cmdInputText.text = ""
|
||||
else
|
||||
cmdInputText.text = commandHistory[commandHistoryIndex]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
engine.debug:output(function(msg, type)
|
||||
if #consoleController.outputLines > 100 then
|
||||
table.remove(consoleController.outputLines, 1)
|
||||
end
|
||||
table.insert(consoleController.outputLines, {msg, type})
|
||||
|
||||
local text = ""
|
||||
|
||||
for _,v in pairs (consoleController.outputLines) do
|
||||
local colour = (v[2] == 1) and "#ff0000" or "#ffffff"
|
||||
if text ~= "" then
|
||||
text = string.format("%s\n%s%s", text, colour, v[1])
|
||||
else
|
||||
text = string.format("%s%s", colour, v[1])
|
||||
end
|
||||
end
|
||||
|
||||
-- deprecated but it's the only way to do color afaik
|
||||
entryLabel:setText(text)
|
||||
|
||||
local size = stringCount(text, "\n")*20+20
|
||||
|
||||
entryLabel.size = guiCoord(1, -10, 0, size)
|
||||
scrollView.canvasSize = guiCoord(0, 0, 0, size)
|
||||
end)
|
||||
end
|
||||
|
||||
return consoleController
|
|
@ -1,134 +0,0 @@
|
|||
local controller = {
|
||||
|
||||
contextLastOpenedAt = nil,
|
||||
activeContextMenu = nil
|
||||
|
||||
}
|
||||
|
||||
local ui = require("tevgit:create/controllers/ui.lua")
|
||||
|
||||
local function mouseOutOfBounds(tpLeft, btmRight)
|
||||
local vec2 = engine.input.mousePosition
|
||||
return (not (vec2.x > tpLeft.x and vec2.y > tpLeft.y and vec2.x < btmRight.x and vec2.y < btmRight.y))
|
||||
end
|
||||
|
||||
function controller.create(options)
|
||||
local frame = engine.guiFrame()
|
||||
frame.size = guiCoord(0, 200, 0, 0)
|
||||
frame.cropChildren = false
|
||||
frame.zIndex = 2
|
||||
ui.theme.add(frame, "main")
|
||||
|
||||
local position = guiCoord(0, 15, 0, 10)
|
||||
local size = guiCoord(1, 0, 0, 20)
|
||||
local offsetY = guiCoord(0, 0, 0, 40)
|
||||
|
||||
for key, data in next, options do
|
||||
local option = data.subOptions and engine.guiTextBox() or engine.guiButton()
|
||||
option.position = position
|
||||
option.size = size
|
||||
option.align = enums.align.middleLeft
|
||||
option.cropChildren = false
|
||||
option.text = key
|
||||
ui.theme.add(option, "primaryText")
|
||||
if (data.subOptions) then
|
||||
local subframe = controller.create(data.subOptions)
|
||||
ui.theme.add(subframe, "secondary")
|
||||
subframe.position = guiCoord(1, -15, 0, -10)
|
||||
subframe.visible = false
|
||||
subframe.parent = option
|
||||
|
||||
local isShowing = false
|
||||
|
||||
option:mouseFocused(function()
|
||||
if (not isShowing) then
|
||||
isShowing = true
|
||||
|
||||
subframe.position = guiCoord(1, -15, 0, -10)
|
||||
if (engine.input.mousePosition.y > engine.input.screenSize.y - subframe.size.offsetY) then
|
||||
subframe.position = subframe.position + guiCoord(0, 0, 0, -(subframe.size.offsetY - 40))
|
||||
end
|
||||
if (engine.input.mousePosition.x > engine.input.screenSize.x - frame.size.offsetX) then
|
||||
subframe.position = subframe.position + guiCoord(-1, -frame.size.offsetX, 0, 0)
|
||||
end
|
||||
|
||||
subframe.visible = true
|
||||
repeat wait()
|
||||
until controller.activeContextMenu == nil or (
|
||||
mouseOutOfBounds(subframe.absolutePosition, subframe.absolutePosition + subframe.absoluteSize)
|
||||
and mouseOutOfBounds(option.absolutePosition, option.absolutePosition + option.absoluteSize)
|
||||
)
|
||||
if (controller.activeContextMenu ~= nil) then
|
||||
isShowing = false
|
||||
subframe.visible = false
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
option:mouseLeftReleased(function()
|
||||
if (frame and controller.activeContextMenu and (controller.activeContextMenu == frame or frame:isDescendantOf(controller.activeContextMenu))) then
|
||||
controller.activeContextMenu:destroy()
|
||||
controller.activeContextMenu = nil
|
||||
end
|
||||
data.action()
|
||||
end)
|
||||
end
|
||||
if (data.subOptions or data.hotkey) then
|
||||
local subtext = engine.guiTextBox()
|
||||
subtext.text = data.hotkey or ">"
|
||||
subtext.size = guiCoord(1, 0, 1, 0)
|
||||
subtext.position = guiCoord(0, -30, 0, 0)
|
||||
subtext.handleEvents = false
|
||||
subtext.align = enums.align.middleRight
|
||||
ui.theme.add(subtext, "secondaryText")
|
||||
subtext.parent = option
|
||||
end
|
||||
frame.size = frame.size + offsetY
|
||||
position = position + offsetY
|
||||
option.parent = frame
|
||||
end
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
function controller.display(contextMenu)
|
||||
if (controller.activeContextMenu) then
|
||||
controller.activeContextMenu:destroy()
|
||||
controller.activeContextMenu = nil
|
||||
end
|
||||
local pos = engine.input.mousePosition
|
||||
contextMenu.position = guiCoord(0, pos.x, 0, pos.y)
|
||||
if (engine.input.mousePosition.y > engine.input.screenSize.y - contextMenu.size.offsetY) then
|
||||
contextMenu.position = contextMenu.position + guiCoord(0, 0, 0, -contextMenu.size.offsetY)
|
||||
end
|
||||
if (engine.input.mousePosition.x > engine.input.screenSize.x - contextMenu.size.offsetX) then
|
||||
contextMenu.position = contextMenu.position + guiCoord(0, -contextMenu.size.offsetX, 0, 0)
|
||||
end
|
||||
contextMenu.parent = ui.workshop.interface
|
||||
contextLastOpenedAt = engine.input.mousePosition
|
||||
controller.activeContextMenu = contextMenu
|
||||
end
|
||||
|
||||
function controller.bind(object, options)
|
||||
local listener = object:mouseRightReleased(function()
|
||||
if type(options) == "function" then
|
||||
controller.display(controller.create(options()))
|
||||
else
|
||||
controller.display(controller.create(options))
|
||||
end
|
||||
end)
|
||||
return listener
|
||||
end
|
||||
|
||||
engine.input:mouseLeftReleased(function()
|
||||
if (controller.activeContextMenu) then
|
||||
local tpLeft = controller.activeContextMenu.absolutePosition
|
||||
local btmRight = tpLeft + controller.activeContextMenu.absoluteSize
|
||||
if (mouseOutOfBounds(tpLeft, btmRight)) then
|
||||
controller.activeContextMenu:destroy()
|
||||
controller.activeContextMenu = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
return controller
|
|
@ -1,23 +0,0 @@
|
|||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local selectionController = require("tevgit:create/controllers/select.lua")
|
||||
local propertyController = require("tevgit:create/controllers/propertyEditor.lua")
|
||||
|
||||
local light = toolsController.createButton("createTab", "fa:s-lightbulb", "Light")
|
||||
light:mouseLeftReleased(function ()
|
||||
local l = engine.construct("light", workspace, {
|
||||
position = workspace.camera.position - (workspace.camera.rotation * vector3(0,0,5))
|
||||
})
|
||||
|
||||
propertyController.generateProperties(l)
|
||||
end)
|
||||
|
||||
local script = toolsController.createButton("createTab", "fa:s-microchip", "Script")
|
||||
script:mouseLeftReleased(function ()
|
||||
require("tevgit:create/controllers/scriptController.lua").newScriptDialogue(workspace)
|
||||
end)
|
||||
|
||||
-- temp:
|
||||
local graphicsSettings = toolsController.createButton("topBar", "fa:s-cogs", "Graphics")
|
||||
graphicsSettings:mouseLeftReleased(function ()
|
||||
propertyController.generateProperties(engine.graphics)
|
||||
end)
|
|
@ -1,62 +0,0 @@
|
|||
-- Mean to be a module dedicated to debugging create mode?
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
local uiTabController = require("tevgit:create/controllers/uiTabController.lua")
|
||||
|
||||
|
||||
uiController.devTab = uiController.createFrame(uiController.workshop.interface, {
|
||||
name = "devTab",
|
||||
size = guiCoord(1, 0, 0, 60),
|
||||
position = guiCoord(0,0,0,23)
|
||||
}, "mainTopBar")
|
||||
|
||||
uiTabController.createTab(uiController.tabs, "Dev [ignore this]", uiController.devTab)
|
||||
|
||||
|
||||
toolsController.registerMenu("devTab", uiController.devTab)
|
||||
|
||||
local reloadButton = toolsController.createButton("devTab", "fa:s-sync", "Reload all")
|
||||
reloadButton:mouseLeftReleased(function ()
|
||||
engine.input.cursorTexture = "fa:s-mouse-pointer"
|
||||
uiController.workshop:reloadCreate()
|
||||
end)
|
||||
|
||||
|
||||
local reloadShadersButton = toolsController.createButton("devTab", "fa:s-sync", "Shaders")
|
||||
reloadShadersButton:mouseLeftReleased(function ()
|
||||
uiController.workshop:reloadShaders()
|
||||
end)
|
||||
|
||||
|
||||
local gcWindow = uiController.createWindow(uiController.workshop.interface, guiCoord(0.5, -150, 0, 300), guiCoord(0, 300, 0, 93), "GC", true) --undockable window
|
||||
gcWindow.visible = false
|
||||
gcWindow.zIndex = 2000
|
||||
|
||||
local gcText = uiController.create("guiTextBox", gcWindow.content, {
|
||||
size = guiCoord(1,-20,1,-40),
|
||||
position = guiCoord(0,10,0,10),
|
||||
wrap = true
|
||||
}, "mainText")
|
||||
|
||||
local gcnow = uiController.create("guiButton", gcWindow.content, {
|
||||
size = guiCoord(1,-20,0,20),
|
||||
position= guiCoord(0,10,1,-25),
|
||||
text = "collectgarbage()"
|
||||
}, "main")
|
||||
|
||||
gcnow:mouseLeftReleased(function ()
|
||||
collectgarbage()
|
||||
end)
|
||||
|
||||
local garbageButton = toolsController.createButton("devTab", "fa:s-trash-alt", "GC")
|
||||
garbageButton:mouseLeftReleased(function ()
|
||||
gcWindow.visible = not gcWindow.visible
|
||||
|
||||
spawnThread(function ()
|
||||
while gcWindow.visible do
|
||||
gcText.text = string.format("Memory Usage %.3f MB", collectgarbage( "count" ) / 1024)
|
||||
wait(.1)
|
||||
end
|
||||
end)
|
||||
end)
|
|
@ -1,322 +0,0 @@
|
|||
local controller = {}
|
||||
|
||||
controller.ui = nil
|
||||
controller.dockDictionary = {}
|
||||
controller.bottomDock = {}
|
||||
controller.rightDock = {}
|
||||
|
||||
local luaHelpers = require("tevgit:create/helpers.lua")
|
||||
local lastUpdate = os.clock()
|
||||
local pendingSave = false
|
||||
local saveDocks = function()
|
||||
if pendingSave then return end
|
||||
pendingSave = true
|
||||
repeat
|
||||
wait()
|
||||
until os.clock() - lastUpdate > 5 -- delay so we're sure user has stopped messing with the layout
|
||||
|
||||
local setting = {
|
||||
bottomDock = {},
|
||||
rightDock = {}
|
||||
}
|
||||
|
||||
for i,v in pairs(controller.bottomDock) do
|
||||
table.insert(setting.bottomDock, {i, v.titleBar.textLabel.text})
|
||||
end
|
||||
|
||||
for i,v in pairs(controller.rightDock) do
|
||||
table.insert(setting.rightDock, {i, v.titleBar.textLabel.text})
|
||||
end
|
||||
|
||||
print("Saving dock layout")
|
||||
controller.ui.workshop:setSettings("docks", setting)
|
||||
pendingSave = false
|
||||
end
|
||||
|
||||
local function sorter(a, b)
|
||||
return a[1] < b[1]
|
||||
end
|
||||
|
||||
controller.loadSettings = function()
|
||||
local setting = controller.ui.workshop:getSettings("docks")
|
||||
if setting then
|
||||
print("Restoring dock layout")
|
||||
local easyWay = {}
|
||||
|
||||
for i,v in pairs(controller.bottomDock) do
|
||||
easyWay[v.titleBar.textLabel.text] = v
|
||||
v.position = v.position - guiCoord(0,0,0,30)
|
||||
end
|
||||
|
||||
for i,v in pairs(controller.rightDock) do
|
||||
easyWay[v.titleBar.textLabel.text] = v
|
||||
--print(v.titleBar.textLabel.text, v)
|
||||
v.position = v.position - guiCoord(0,30,0,0)
|
||||
end
|
||||
|
||||
controller.bottomDock = {}
|
||||
controller.rightDock = {}
|
||||
controller.dockDictionary = {}
|
||||
|
||||
table.sort(setting.bottomDock, sorter)
|
||||
|
||||
for i,v in ipairs(setting.bottomDock) do
|
||||
--print("look:", v)
|
||||
if easyWay[v[2]] then
|
||||
controller.dockWindow(easyWay[v[2]], controller.bottomDock)
|
||||
-- print("dockng")
|
||||
easyWay[v[2]] = nil
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(setting.rightDock, sorter)
|
||||
for i,v in ipairs(setting.rightDock) do
|
||||
if easyWay[v[2]] then
|
||||
controller.dockWindow(easyWay[v[2]], controller.rightDock)
|
||||
easyWay[v[2]] = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- direction: up, down, left or right
|
||||
local function renderHelper(parent, direction, pos)
|
||||
local frame = controller.ui.create("guiFrame", parent, {
|
||||
name = "locationHelper" .. direction,
|
||||
size = guiCoord(0, 40, 0, 40),
|
||||
borderRadius = 5,
|
||||
borderWidth = 1,
|
||||
borderAlpha = 1
|
||||
}, "light")
|
||||
|
||||
if pos then
|
||||
frame.position = pos
|
||||
end
|
||||
|
||||
controller.ui.create("guiImage", frame, {
|
||||
size = guiCoord(0, 12, 0, 12),
|
||||
position = guiCoord(0.5,-6,0,5),
|
||||
texture = "fa:s-arrow-" .. direction
|
||||
}, "light")
|
||||
|
||||
controller.ui.create("guiImage", frame, {
|
||||
size = guiCoord(0, 18, 0, 18),
|
||||
position = guiCoord(0.5,-9,0,18),
|
||||
backgroundAlpha = 0.75,
|
||||
texture = "fa:r-window-maximize"
|
||||
}, "light")
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
controller.renderDockLocationHelpers = function()
|
||||
local helpers = engine.construct("guiFrame", controller.ui.workshop.interface, { zIndex=100, size = guiCoord(1,0,1,0), backgroundAlpha = 0, handleEvents=false})
|
||||
|
||||
local outline = controller.ui.create("guiFrame", helpers, {
|
||||
name = "outline",
|
||||
size = guiCoord(0, 100, 0, 220),
|
||||
backgroundAlpha = 0,
|
||||
borderRadius = 2,
|
||||
borderWidth = 1,
|
||||
borderAlpha = 1,
|
||||
visible = false
|
||||
}, "light")
|
||||
|
||||
if #controller.bottomDock == 0 then
|
||||
renderHelper(helpers, "down", guiCoord(0.5, -20, 0.9, -20))
|
||||
else
|
||||
for i,v in pairs(controller.bottomDock) do
|
||||
renderHelper(helpers, "down", guiCoord(0, v.absolutePosition.y + 20, 0.9, -20))
|
||||
if i == #controller.bottomDock then
|
||||
renderHelper(helpers, "down", guiCoord(0, v.absolutePosition.y + v.absoluteSize.y - 40, 0.9, -20))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #controller.rightDock == 0 then
|
||||
renderHelper(helpers, "right", guiCoord(0.9, -20, 0.5, -20))
|
||||
else
|
||||
for i,v in pairs(controller.rightDock) do
|
||||
renderHelper(helpers, "right", guiCoord(0.9, -20, 0, v.absolutePosition.y + 20))
|
||||
if i == #controller.rightDock then
|
||||
renderHelper(helpers, "right", guiCoord(0.9, -20, 0, v.absolutePosition.y + v.absoluteSize.y - 40))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return helpers
|
||||
end
|
||||
|
||||
controller.undockWindow = function(window)
|
||||
local dockDic = controller.dockDictionary[window]
|
||||
controller.dockDictionary[window] = nil
|
||||
if dockDic then
|
||||
if dockDic == 0 then
|
||||
local foundi = nil
|
||||
for i,v in pairs(controller.bottomDock) do
|
||||
if v == window then
|
||||
controller.bottomDock[i] = nil
|
||||
foundi = i
|
||||
|
||||
|
||||
|
||||
elseif foundi and i > foundi then
|
||||
controller.bottomDock[i-1] = v
|
||||
controller.bottomDock[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local scale = 1
|
||||
if #controller.rightDock > 0 then
|
||||
scale = 0.8
|
||||
end
|
||||
|
||||
|
||||
for i,v in pairs(controller.bottomDock) do
|
||||
-- No tween because other parts of the script needs to read the size and position instantly.
|
||||
v.size = guiCoord(scale*(1/#controller.bottomDock), 0, 0.2, 0)
|
||||
v.position = guiCoord(scale*((i-1) * (1/#controller.bottomDock)), 0, 0.8, 0)
|
||||
end
|
||||
|
||||
elseif dockDic == 1 then
|
||||
|
||||
local foundi = nil
|
||||
for i,v in pairs(controller.rightDock) do
|
||||
if v == window then
|
||||
controller.rightDock[i] = nil
|
||||
foundi = i
|
||||
elseif foundi and i > foundi then
|
||||
controller.rightDock[i-1] = v
|
||||
controller.rightDock[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
for i,v in pairs(controller.rightDock) do
|
||||
-- No tween because other parts of the script needs to read the size and position instantly.
|
||||
v.size = guiCoord(0.2, 0, 1/#controller.rightDock, i == 1 and -83 or 0)
|
||||
v.position = guiCoord(0.8,0,(i-1) * (1/#controller.rightDock), i == 1 and 83 or 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
controller.dockWindow = function(window, dock, pos)
|
||||
controller.undockWindow(window)
|
||||
if dock == controller.bottomDock then
|
||||
controller.dockDictionary[window] = 0
|
||||
--table.insert(controller.bottomDock, window)
|
||||
local newIndex = (pos and pos or 0 / (1/#controller.bottomDock+1)) + 1
|
||||
if newIndex ~= math.floor(newIndex) then
|
||||
newIndex = #controller.bottomDock + 1
|
||||
end
|
||||
if pos and #controller.bottomDock > 0 and newIndex <= #controller.bottomDock then
|
||||
for i = #controller.bottomDock, 1, -1 do
|
||||
if i >= newIndex then
|
||||
controller.bottomDock[i+1] = controller.bottomDock[i]
|
||||
end
|
||||
if i == newIndex then
|
||||
controller.bottomDock[i] = window
|
||||
end
|
||||
end
|
||||
else
|
||||
controller.bottomDock[#controller.bottomDock+1] = window
|
||||
end
|
||||
|
||||
local scale = 1
|
||||
if #controller.rightDock > 0 then
|
||||
scale = 0.8
|
||||
end
|
||||
|
||||
for i,v in pairs(controller.bottomDock) do
|
||||
v.size = guiCoord(scale*(1/#controller.bottomDock), 0, 0.2, 0)
|
||||
v.position = guiCoord(scale*((i-1) * (1/#controller.bottomDock)), 0, 0.8, 0)
|
||||
end
|
||||
elseif dock == controller.rightDock then
|
||||
controller.dockDictionary[window] = 1
|
||||
--table.insert(controller.rightDock, window)
|
||||
local newIndex = (pos and pos or 0 / (1/#controller.rightDock+1)) + 1
|
||||
if newIndex ~= math.floor(newIndex) then
|
||||
newIndex = #controller.rightDock + 1
|
||||
end
|
||||
if pos and #controller.rightDock > 0 and newIndex <= #controller.rightDock then
|
||||
for i = #controller.rightDock, 1, -1 do
|
||||
if i >= newIndex then
|
||||
controller.rightDock[i+1] = controller.rightDock[i]
|
||||
end
|
||||
if i == newIndex then
|
||||
controller.rightDock[i] = window
|
||||
end
|
||||
end
|
||||
else
|
||||
controller.rightDock[#controller.rightDock+1] = window
|
||||
end
|
||||
|
||||
for i,v in pairs(controller.rightDock) do
|
||||
v.size = guiCoord(0.2, 0, 1/#controller.rightDock, i == 1 and -83 or 0)
|
||||
v.position = guiCoord(0.8,0,(i-1) * (1/#controller.rightDock), i == 1 and 83 or 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- window should be a window created in ui.lua... it's a guiframe consisting of other guis.
|
||||
-- this function should be called when the user begins dragging on a window
|
||||
controller.beginWindowDrag = function(window, dontDock)
|
||||
controller.undockWindow(window)
|
||||
local offset = window.absolutePosition - engine.input.mousePosition
|
||||
local startAlpha = window.backgroundAlpha
|
||||
local startZ = window.zIndex
|
||||
window.zIndex = 99
|
||||
|
||||
window.backgroundAlpha = startAlpha*0.5;
|
||||
|
||||
local helpers
|
||||
if not dontDock then
|
||||
helpers = controller.renderDockLocationHelpers()
|
||||
end
|
||||
|
||||
local selectedPosition = window.position
|
||||
local selectedSize = window.size
|
||||
|
||||
while engine.input:isMouseButtonDown(enums.mouseButton.left) do
|
||||
local newpos = engine.input.mousePosition + offset
|
||||
window.position = guiCoord(0, newpos.x, 0, newpos.y)
|
||||
|
||||
if not dontDock then
|
||||
if engine.input.mousePosition.y >= engine.input.screenSize.y * 0.75 and
|
||||
engine.input.mousePosition.x < engine.input.screenSize.x * 0.75 then
|
||||
helpers.outline.size = guiCoord(1/(#controller.bottomDock+1), 0, 0.2, 0)
|
||||
helpers.outline.position = guiCoord(luaHelpers.roundToMultiple(engine.input.mousePosition.x/engine.input.screenSize.x, 1/(#controller.bottomDock+1)), 0, 0.8, 0)
|
||||
helpers.outline.visible = true
|
||||
elseif engine.input.mousePosition.x >= engine.input.screenSize.x * 0.75 then
|
||||
helpers.outline.size = guiCoord(0.2, 0, 1/(#controller.rightDock+1), 0)
|
||||
helpers.outline.position = guiCoord(0.8, 0, luaHelpers.roundToMultiple(engine.input.mousePosition.y/engine.input.screenSize.y, 1/(#controller.rightDock+1)), 0)
|
||||
helpers.outline.visible = true
|
||||
else
|
||||
helpers.outline.visible = false
|
||||
end
|
||||
end
|
||||
|
||||
wait()
|
||||
end
|
||||
local start = os.clock()
|
||||
if not dontDock then
|
||||
helpers:destroy()
|
||||
|
||||
if engine.input.mousePosition.y >= engine.input.screenSize.y * 0.75 and
|
||||
engine.input.mousePosition.x < engine.input.screenSize.x * 0.75 then
|
||||
controller.dockWindow(window, controller.bottomDock, luaHelpers.roundToMultiple(engine.input.mousePosition.x/engine.input.screenSize.x, 1/(#controller.bottomDock+1)))
|
||||
elseif engine.input.mousePosition.x >= engine.input.screenSize.x * 0.75 then
|
||||
controller.dockWindow(window, controller.rightDock, luaHelpers.roundToMultiple(engine.input.mousePosition.y/engine.input.screenSize.y, 1/(#controller.rightDock+1)))
|
||||
end
|
||||
end
|
||||
|
||||
window.backgroundAlpha = startAlpha
|
||||
window.zIndex = startZ
|
||||
|
||||
lastUpdate = os.clock()
|
||||
saveDocks()
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,102 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- environment.lua
|
||||
|
||||
local environmentController = {}
|
||||
|
||||
local firstRun = true
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
--[[
|
||||
local physicsButton = toolsController.createButton("testingTab", "fa:s-pause", "Pause")
|
||||
physicsButton:mouseLeftReleased(function ()
|
||||
if engine.physics.running then
|
||||
engine.physics:pause()
|
||||
else
|
||||
engine.physics:resume()
|
||||
end
|
||||
end)
|
||||
]]
|
||||
|
||||
|
||||
|
||||
--[[
|
||||
engine.physics:changed(function (p,v)
|
||||
if p == "running" then
|
||||
if v then
|
||||
physicsButton.image.texture = "fa:s-pause"
|
||||
physicsButton.text.text = "Pause"
|
||||
else
|
||||
physicsButton.image.texture = "fa:s-play"
|
||||
physicsButton.text.text = "Resume"
|
||||
end
|
||||
end
|
||||
end)]]
|
||||
|
||||
environmentController.createStarterMap = function()
|
||||
print("creating starter map")
|
||||
local mainLight = engine.construct("light", workspace, {
|
||||
name = "mainLight",
|
||||
position = vector3(3, 2, 0),
|
||||
type = enums.lightType.point,
|
||||
rotation = quaternion():setEuler(math.rad(-40), math.rad(25), 0),
|
||||
shadows = true,
|
||||
power = 2
|
||||
})
|
||||
|
||||
local basePlate = engine.construct("block", workspace, {
|
||||
name = "basePlate",
|
||||
colour = colour(0.6, 0.6, 0.6),
|
||||
size = vector3(100, 1, 100),
|
||||
position = vector3(0, -1, 0),
|
||||
workshopLocked = true
|
||||
})
|
||||
|
||||
engine.construct("block", workspace, {
|
||||
name = "redBlock",
|
||||
colour = colour(1, 0, 0),
|
||||
size = vector3(1, 1, 1),
|
||||
position = vector3(0, 0, 0)
|
||||
})
|
||||
|
||||
engine.construct("block", workspace, {
|
||||
name = "greenBlock",
|
||||
colour = colour(0, 1, 0),
|
||||
size = vector3(1, 1, 1),
|
||||
position = vector3(1, 0, 0),
|
||||
mesh = "primitive:wedge",
|
||||
rotation = quaternion:setEuler(0, math.rad(-90), 0)
|
||||
})
|
||||
|
||||
local block = engine.construct("block", workspace, {
|
||||
name = "blueBlock",
|
||||
colour = colour(0, 0, 1),
|
||||
size = vector3(1, 1, 1),
|
||||
position = vector3(0.5, 1, 0),
|
||||
mesh = "primitive:sphere"
|
||||
})
|
||||
|
||||
|
||||
--[[
|
||||
-- Create a script source.
|
||||
-- Noting that this API was not supposed to be used by Developers.
|
||||
-- It is most likely only going to be used internally by our engine.
|
||||
|
||||
-- The idea is that a developer can update this script source and multiple "containers" can use one source.
|
||||
local scriptSource = engine.construct("scriptSource", engine.assets.lua.shared, {
|
||||
name = "main",
|
||||
source = "print('test')"
|
||||
})
|
||||
|
||||
-- Create a script container, this container is responsible for executing code referenced from a script source.
|
||||
-- Each container is treat as its own script and gets its own sandbox.
|
||||
local scriptRunner = engine.construct("scriptContainer", engine.workspace, {name = "mainRunner"})
|
||||
scriptRunner.source = scriptSource -- autoruns if autorun is true (defaults to true)
|
||||
]]
|
||||
end
|
||||
|
||||
environmentController.setDefault = function()
|
||||
engine.graphics.clearColour = colour:fromRGB(56,56,66)
|
||||
engine.graphics.ambientColour = colour:fromRGB(235, 235, 235)
|
||||
end
|
||||
|
||||
return environmentController
|
|
@ -1,238 +0,0 @@
|
|||
local controller = {}
|
||||
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
local dockController = require("tevgit:create/controllers/dock.lua")
|
||||
local selectionController = require("tevgit:create/controllers/select.lua")
|
||||
local propertyEditor = require("tevgit:create/controllers/propertyEditor.lua")
|
||||
local contextMenu = require("tevgit:create/controllers/contextMenu.lua")
|
||||
|
||||
local luaFolderContextOptions = {
|
||||
["new scriptSource"] = {
|
||||
action = function ()
|
||||
if #selectionController.selection == 1 then
|
||||
local folder = selectionController.selection[1]
|
||||
if folder:isA("luaSharedFolder") or folder:isA("luaServerFolder") or folder:isA("luaClientFolder") then
|
||||
local newSource = engine.scriptSource()
|
||||
newSource.parent = folder
|
||||
newSource.name = "newScriptSource"
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
local overridingIcons = {
|
||||
scriptSource = "fa:s-file-code",
|
||||
scriptContainer = "fa:s-microchip",
|
||||
input = {"fa:s-keyboard", "fa:r-keyboard"},
|
||||
debug = "fa:s-bug",
|
||||
light = "fa:s-lightbulb",
|
||||
block = "fa:s-cube",
|
||||
camera = "fa:s-camera"
|
||||
}
|
||||
|
||||
--dictionary of buttons to their corrosponding objects.
|
||||
local buttonToObject = {}
|
||||
|
||||
local function updatePositions(frame)
|
||||
local y = 10
|
||||
if not frame then
|
||||
frame = controller.scrollView
|
||||
else
|
||||
y = 20
|
||||
end
|
||||
|
||||
if frame.children then
|
||||
for _,v in pairs(frame.children) do
|
||||
if v.name ~= "icon" then
|
||||
v.position = guiCoord(0, 10, 0, y)
|
||||
y = y + updatePositions(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if type(frame) == "guiTextBox" then
|
||||
|
||||
local regularIconWithChildren = "fa:s-folder"
|
||||
local regularIconWithOutChildren = "fa:r-folder"
|
||||
local expandedIcon = "fa:s-folder-open"
|
||||
|
||||
local icons = overridingIcons[buttonToObject[frame].className]
|
||||
if icons then
|
||||
if type(icons) == "string" then
|
||||
regularIconWithChildren = icons
|
||||
regularIconWithOutChildren = icons
|
||||
else
|
||||
regularIconWithChildren = icons[1]
|
||||
regularIconWithOutChildren = icons[1]
|
||||
expandedIcon = icons[2]
|
||||
end
|
||||
end
|
||||
|
||||
if y == 20 then
|
||||
-- no children
|
||||
if buttonToObject[frame] and buttonToObject[frame].children and #buttonToObject[frame].children > 0 then
|
||||
--object has children but is not expanded
|
||||
frame.icon.texture = regularIconWithChildren
|
||||
frame.icon.imageAlpha = 1
|
||||
frame.textAlpha = 1
|
||||
frame.fontFile = "OpenSans-SemiBold.ttf"
|
||||
else
|
||||
--object has no children
|
||||
frame.icon.texture = regularIconWithOutChildren
|
||||
frame.icon.imageAlpha = .2
|
||||
frame.textAlpha = .6
|
||||
frame.fontFile = "OpenSans-Regular.ttf"
|
||||
end
|
||||
else
|
||||
-- object is expanded
|
||||
frame.textAlpha = 0.6
|
||||
frame.fontFile = "OpenSans-Regular.ttf"
|
||||
frame.icon.imageAlpha = 0.4
|
||||
frame.icon.texture = expandedIcon
|
||||
end
|
||||
|
||||
if buttonToObject[frame] and selectionController.isSelected(buttonToObject[frame]) then
|
||||
frame.backgroundAlpha = 0.3
|
||||
else
|
||||
frame.backgroundAlpha = 0
|
||||
end
|
||||
end
|
||||
|
||||
return y
|
||||
end
|
||||
|
||||
controller.updatePositions = updatePositions
|
||||
|
||||
local function createHierarchyButton(object, guiParent)
|
||||
local btn = uiController.create("guiTextBox", guiParent, {
|
||||
text = " " .. object.name, --ik...
|
||||
size = guiCoord(1, -6, 0, 18),
|
||||
fontSize = 16,
|
||||
cropChildren = false,
|
||||
backgroundAlpha = 0,
|
||||
hoverCursor = "fa:s-hand-pointer"
|
||||
}, "main")
|
||||
|
||||
buttonToObject[btn] = object
|
||||
|
||||
local icon = uiController.create("guiImage", btn, {
|
||||
name = "icon",
|
||||
texture = "fa:s-folder",
|
||||
position = guiCoord(0, 1, 0, 1),
|
||||
size = guiCoord(0, 16, 0, 16),
|
||||
handleEvents = false,
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
local expanded = false
|
||||
local lastClick = 0
|
||||
|
||||
|
||||
btn:onSync("mouseRightPressed", function()
|
||||
if (object:isA("folder")) then
|
||||
selectionController.setSelection(object.children)
|
||||
propertyEditor.generateProperties(object)
|
||||
else
|
||||
selectionController.setSelection({object})
|
||||
end
|
||||
controller.scrollView.canvasSize = guiCoord(1, 0, 0, updatePositions())
|
||||
end)
|
||||
|
||||
btn:mouseLeftReleased(function()
|
||||
if os.time() - lastClick < 0.35 then
|
||||
lastClick = 0
|
||||
--expand
|
||||
expanded = not expanded
|
||||
if expanded then
|
||||
for _,child in pairs(object.children) do
|
||||
createHierarchyButton(child, btn)
|
||||
end
|
||||
controller.scrollView.canvasSize = guiCoord(1, 0, 0, updatePositions())
|
||||
if object.className == "scriptSource" or object.className == "scriptContainer" then
|
||||
require("tevgit:create/controllers/scriptController.lua").editScript(object)
|
||||
end
|
||||
else
|
||||
for _,v in pairs(btn.children) do
|
||||
if v.name ~= "icon" then
|
||||
if buttonToObject[v] then
|
||||
buttonToObject[v] = nil
|
||||
end
|
||||
v:destroy()
|
||||
end
|
||||
end
|
||||
controller.scrollView.canvasSize = guiCoord(1, 0, 0, updatePositions())
|
||||
end
|
||||
else
|
||||
--single click
|
||||
local currentTime = os.time()
|
||||
lastClick = currentTime
|
||||
|
||||
|
||||
if (object:isA("folder")) then
|
||||
selectionController.setSelection(object.children)
|
||||
propertyEditor.generateProperties(object)
|
||||
else
|
||||
selectionController.setSelection({object})
|
||||
end
|
||||
|
||||
controller.scrollView.canvasSize = guiCoord(1, 0, 0, updatePositions())
|
||||
end
|
||||
end)
|
||||
|
||||
local childAddedEvent = object:on("childAdded", function (child)
|
||||
if expanded then
|
||||
createHierarchyButton(child, btn)
|
||||
end
|
||||
controller.scrollView.canvasSize = guiCoord(1, 0, 0, updatePositions())
|
||||
end)
|
||||
|
||||
local childRemovedEvent = object:onSync("childRemoved", function (child)
|
||||
if expanded then
|
||||
for button,obj in pairs(buttonToObject) do
|
||||
if obj == child and button.alive then
|
||||
button:destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
controller.scrollView.canvasSize = guiCoord(1, 0, 0, updatePositions())
|
||||
end)
|
||||
|
||||
btn:once("destroying", function ()
|
||||
childAddedEvent:disconnect()
|
||||
end)
|
||||
|
||||
if object:isA("luaSharedFolder") or object:isA("luaServerFolder") or object:isA("luaClientFolder") then
|
||||
contextMenu.bind(btn, luaFolderContextOptions)
|
||||
else
|
||||
selectionController.applyContext(btn)
|
||||
end
|
||||
return btn
|
||||
end
|
||||
|
||||
function controller.createUI(workshop)
|
||||
controller.window = uiController.createWindow(workshop.interface,
|
||||
guiCoord(1, -300, 1, -400), -- pos
|
||||
guiCoord(0, 250, 0, 400), -- size
|
||||
"Hierarchy")
|
||||
controller.window.visible = true
|
||||
|
||||
dockController.dockWindow(controller.window, dockController.rightDock)
|
||||
|
||||
controller.scrollView = uiController.create("guiScrollView", controller.window.content, {
|
||||
name = "scrollview",
|
||||
size = guiCoord(1, 0, 1, 0)
|
||||
}, "mainTopBar")
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local hierarchyBtn = toolsController.createButton("windowsTab", "fa:s-sitemap", "Hierarchy")
|
||||
hierarchyBtn:mouseLeftReleased(function ()
|
||||
controller.window.visible = not controller.window.visible
|
||||
end)
|
||||
|
||||
createHierarchyButton(engine, controller.scrollView)
|
||||
controller.scrollView.canvasSize = guiCoord(1, 0, 0, updatePositions())
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,205 +0,0 @@
|
|||
--[[
|
||||
Copyright 2019 Teverse
|
||||
@File history.lua
|
||||
@Author(s) Neztore
|
||||
--]]
|
||||
-- Manages undo/redo points. A stack type thing so we don't guzzle memory.
|
||||
-- Config
|
||||
local undoSize = 50
|
||||
local redoSize = 20
|
||||
|
||||
-- Lists are stack like, but they fill up to 50 and then return to the start and just overwrite previous points.
|
||||
local pointer = 0
|
||||
local undoList = {}
|
||||
|
||||
local redoPointer = 0
|
||||
local redoList = {}
|
||||
|
||||
local workshop
|
||||
|
||||
function getWorkshop (ws)
|
||||
workshop = ws
|
||||
end
|
||||
|
||||
-- TODO: Add support for combined actions (i.e. move multiple items at once)
|
||||
-- TODO: Add buttons
|
||||
-- TODO: Improve stability
|
||||
|
||||
-- HISTORY_CREATED, HISTORY_DELETED: When something is created or deleted the prop will be set to one of these.
|
||||
-- These are named this way to make sure they'll never collide will real props (they never will: underscores are evil - jay)
|
||||
|
||||
-- We only store what is changed
|
||||
function addUndo (object, changedProp, value)
|
||||
if changedProp == "HISTORY_DELETED" then
|
||||
-- Copy properties
|
||||
if object.alive and object.parent and object.parent.alive then
|
||||
local toStore = cloneObject(object)
|
||||
undoList[pointer] = {
|
||||
className = object.className,
|
||||
prop = changedProp,
|
||||
value = toStore
|
||||
}
|
||||
|
||||
else
|
||||
return print("Can't add destroyed object to history")
|
||||
end
|
||||
else
|
||||
|
||||
undoList[pointer] = {
|
||||
obj = object,
|
||||
prop = changedProp,
|
||||
value = value
|
||||
}
|
||||
end
|
||||
|
||||
if pointer >= undoSize then
|
||||
-- We return to start and start overwriting.
|
||||
pointer = 0
|
||||
else
|
||||
pointer = pointer + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Restores the last point on the list
|
||||
function restorePoint ()
|
||||
if pointer == 0 then
|
||||
if undoList[undoSize] then
|
||||
-- The last item exists, so we just go to back. We go to 1+ to account for pointer problems.
|
||||
pointer = undoSize + 1
|
||||
end
|
||||
end
|
||||
|
||||
local point = undoList[pointer - 1]
|
||||
if point then
|
||||
if point.prop == "HISTORY_CREATED" then
|
||||
print("removing created")
|
||||
-- To undo it we delete it. We should also copy the properties in-case it was a copy.
|
||||
local toStore = cloneObject(point.obj)
|
||||
local parent = point.obj.parent
|
||||
|
||||
addRedo(point.obj.className, "HISTORY_CREATED", toStore)
|
||||
point.obj:destroy()
|
||||
|
||||
elseif point.prop == "HISTORY_DELETED" then
|
||||
local parent = point.value.parent
|
||||
if parent then
|
||||
local object = engine.construct(point.className, parent, point.value)
|
||||
addRedo(object, "HISTORY_DELETED")
|
||||
else
|
||||
print("Failed to undo deletion: Parent no longer exists.")
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
print("undoing "..point.prop)
|
||||
-- Normal: it hasn't been deleted.
|
||||
if point.obj and point.obj.alive then
|
||||
local object = point.obj
|
||||
-- not destroyed; reset value to prev & take redo value
|
||||
local redoValue = object[point.prop]
|
||||
addRedo(object, point.prop, redoValue)
|
||||
|
||||
-- Restore value
|
||||
object[point.prop] = point.value
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local object = point.obj
|
||||
undoList[pointer - 1] = nil
|
||||
pointer = pointer - 1
|
||||
|
||||
else
|
||||
print("Nothing left to undo!")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- "Redoes" the last action.
|
||||
function addRedo (object, changedProp, value)
|
||||
redoList[redoPointer] = {
|
||||
obj = object,
|
||||
prop = changedProp,
|
||||
value = value
|
||||
}
|
||||
if redoPointer >= redoSize then
|
||||
-- We return to start and start overwriting.
|
||||
redoPointer = 0
|
||||
else
|
||||
redoPointer = redoPointer + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Opposite of restorePoint
|
||||
function redoAction ()
|
||||
if redoPointer == 0 then
|
||||
if redoList[redoSize] then
|
||||
-- The last item exists, so we just go to back. We go to 1+ to account for pointer problems.
|
||||
redoPointer = redoSize + 1
|
||||
end
|
||||
end
|
||||
|
||||
local point = redoList[redoPointer - 1]
|
||||
|
||||
if point then
|
||||
if point.prop == "HISTORY_CREATED" then
|
||||
-- To redo it we create it. We should have the properties
|
||||
|
||||
local object = engine.construct(point.obj, point.value.parent, point.value)
|
||||
addUndo(object, "HISTORY_CREATED")
|
||||
|
||||
elseif point.prop == "HISTORY_DELETED" then
|
||||
if not point.obj then print("ERROR: Object does not exist.")
|
||||
addUndo(point.obj, "HISTORY_DELETED")
|
||||
point.obj:destroy()
|
||||
else
|
||||
local object = point.obj
|
||||
|
||||
if object and object.alive then
|
||||
-- not destroyed; reset value to prev & take redo value
|
||||
local redoValue = object[point.prop]
|
||||
addUndo(object, point.prop, redoValue)
|
||||
|
||||
-- Restore value
|
||||
object[point.prop] = point.value
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
redoList[redoPointer - 1] = nil
|
||||
redoPointer = redoPointer - 1
|
||||
-- We return so buttons etc. know if it's empty.
|
||||
return true
|
||||
else
|
||||
print("Nothing left to redo!")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function cloneObject (object)
|
||||
local members = workshop:getMembersOfObject( object )
|
||||
local toStore = {}
|
||||
for _, prop in pairs(members) do
|
||||
local val = object[prop.property]
|
||||
local pType = type(val)
|
||||
|
||||
if prop.writable and pType ~= "function" then
|
||||
-- We can save it and re-construct it
|
||||
toStore[prop.property] = val
|
||||
end
|
||||
end
|
||||
toStore["parent"] = object.parent
|
||||
return toStore
|
||||
end
|
||||
|
||||
|
||||
return {
|
||||
addPoint = addUndo,
|
||||
undo = restorePoint,
|
||||
redo = redoAction,
|
||||
giveWorkshop = getWorkshop
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- select.lua
|
||||
|
||||
local hotkeysController = {
|
||||
|
||||
bindings = {}
|
||||
|
||||
}
|
||||
|
||||
local history = require("tevgit:create/controllers/history.lua")
|
||||
|
||||
function hotkeysController:bind(hotkeyData)
|
||||
if (hotkeyData.priorKey) then
|
||||
if (not self.bindings[hotkeyData.priorKey]) then
|
||||
self.bindings[hotkeyData.priorKey] = {}
|
||||
end
|
||||
if (self.bindings[hotkeyData.priorKey][hotkeyData.key]) then
|
||||
error("Hot key " .. hotkeyData.name .. " can not overwrite existing hotkey: " .. self.bindings[hotkeyData.priorKey][hotkeyData.key].name)
|
||||
end
|
||||
self.bindings[hotkeyData.priorKey][hotkeyData.key] = hotkeyData
|
||||
else
|
||||
if (self.bindings[hotkeyData.key]) then
|
||||
error("Hot key " .. hotkeyData.name .. " can not overwrite existing hotkey: " .. self.bindings[hotkeyData.key].name)
|
||||
end
|
||||
self.bindings[hotkeyData.key] = hotkeyData
|
||||
end
|
||||
|
||||
return hotkeyData.action
|
||||
end
|
||||
|
||||
function hotkeysController:handle(inputObject)
|
||||
for key, data in pairs(self.bindings) do
|
||||
if (not data.action) then
|
||||
if (engine.input:isKeyDown(key)) then
|
||||
for key, data in pairs(data) do
|
||||
if (inputObject.key == key) then
|
||||
data.action()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if (inputObject.key == key) then
|
||||
data.action()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
engine.input:keyPressed(function(inputObject)
|
||||
if (inputObject.systemHandled) then
|
||||
return
|
||||
else
|
||||
hotkeysController:handle(inputObject)
|
||||
end
|
||||
end)
|
||||
|
||||
-- @hotkeys Undo/redo so we don't need to require hotkeys in history.lua
|
||||
hotkeysController:bind({
|
||||
name = "undo",
|
||||
priorKey = enums.key.leftCtrl,
|
||||
key = enums.key.z,
|
||||
action = history.undo
|
||||
})
|
||||
|
||||
hotkeysController:bind({
|
||||
name = "redo",
|
||||
priorKey = enums.key.leftCtrl,
|
||||
key = enums.key.y,
|
||||
action = history.redo
|
||||
})
|
||||
|
||||
return hotkeysController
|
|
@ -1,87 +0,0 @@
|
|||
-- Teverse doesn't render anything where lights are...
|
||||
-- This script should render a visible mesh in position of lights to allow the user to see/select them in 3D space.
|
||||
|
||||
local controller = {}
|
||||
|
||||
controller.lights = {}
|
||||
|
||||
controller.registerLight = function(light)
|
||||
assert(type(light) == "light")
|
||||
for _,v in pairs(controller.lights) do
|
||||
if v == light then
|
||||
error("already registered")
|
||||
end
|
||||
end
|
||||
|
||||
local newBlock = engine.construct("block", workspace, {
|
||||
doNotSerialise=true,
|
||||
name = "_CreateMode_Light_Placeholder",
|
||||
size = vector3(0.3, 0.3, 0.3),
|
||||
mesh = "tevurl:3d/light.glb",
|
||||
emissiveColour = light.diffuseColour*20,
|
||||
castsShadows =false,
|
||||
position = light.position,
|
||||
rotation = light.rotation
|
||||
})
|
||||
|
||||
local destroyed = false
|
||||
|
||||
controller.lights[newBlock] = light
|
||||
light:destroying(function ()
|
||||
if not destroyed then
|
||||
destroyed = true
|
||||
controller.lights[newBlock] = nil
|
||||
newBlock:destroy()
|
||||
end
|
||||
end)
|
||||
|
||||
--delay updates to block to lower risk of loop
|
||||
local lastUpdate = nil
|
||||
light:changed(function (k,v)
|
||||
if not lastUpdate and newBlock[k] then
|
||||
lastUpdate = os.time()
|
||||
repeat wait(.1) until os.time() - lastUpdate > 0.6
|
||||
|
||||
newBlock.emissiveColour = (light.diffuseColour * 20):max(colour(0.1,0.1,0.1))
|
||||
|
||||
if newBlock.position ~= light.position then
|
||||
newBlock.position = light.position
|
||||
elseif newBlock.rotation ~= light.rotation then
|
||||
newBlock.rotation = light.rotation
|
||||
end
|
||||
lastUpdate = nil
|
||||
elseif lastUpdate then
|
||||
lastUpdate = os.time()
|
||||
end
|
||||
end)
|
||||
|
||||
newBlock:changed(function (k,v)
|
||||
if k == "position" and light.position ~= v then
|
||||
light.position = v
|
||||
elseif k == "rotation" and light.rotation ~= v then
|
||||
light.rotation = v
|
||||
end
|
||||
end)
|
||||
|
||||
newBlock:destroying(function ()
|
||||
if not destroyed then
|
||||
destroyed = true
|
||||
light:destroy()
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
local function handleChild(c)
|
||||
if type(c) == "light" then
|
||||
print("Registering new light", c)
|
||||
controller.registerLight(c)
|
||||
end
|
||||
end
|
||||
|
||||
workspace:childAdded(handleChild)
|
||||
for _,v in pairs(workspace.children) do
|
||||
handleChild(v)
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,929 +0,0 @@
|
|||
local controller = {}
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
local colourPickerController = require("tevgit:create/extras/colourPicker.lua")
|
||||
local dockController = require("tevgit:create/controllers/dock.lua")
|
||||
|
||||
local meshShorcuts = {
|
||||
cube = "primitive:cube",
|
||||
sphere = "primitive:sphere",
|
||||
cylinder = "primitive:cylinder",
|
||||
torus = "primitive:torus",
|
||||
cone = "primitive:cone",
|
||||
wedge = "primitive:wedge",
|
||||
corner = "primitive:corner",
|
||||
worker = "tevurl:3d/worker.glb",
|
||||
duck = "tevurl:3d/Duck.glb",
|
||||
avocado = "tevurl:3d/Avocado.glb",
|
||||
}
|
||||
|
||||
controller.window = nil
|
||||
controller.workshop = nil
|
||||
controller.scrollView = nil
|
||||
|
||||
controller.excludePropertyList = {}
|
||||
|
||||
controller.colourPicker = nil
|
||||
|
||||
function controller.createUI(workshop)
|
||||
controller.workshop = workshop
|
||||
controller.colourPicker = colourPickerController.create()
|
||||
controller.colourPicker.window.visible = false
|
||||
controller.window = uiController.createWindow(workshop.interface, guiCoord(1, -300, 1, -400), guiCoord(0, 250, 0, 400), "Properties")
|
||||
controller.window.visible = true
|
||||
|
||||
dockController.dockWindow(controller.window, dockController.rightDock)
|
||||
|
||||
controller.scrollView = uiController.create("guiScrollView", controller.window.content, {
|
||||
name = "scrollview",
|
||||
size = guiCoord(1,0,1,-32),
|
||||
position = guiCoord(0,0,0,32)
|
||||
}, "mainTopBar")
|
||||
|
||||
controller.info = uiController.create("guiTextBox", controller.window.content, {
|
||||
name = "info",
|
||||
size = guiCoord(1,-6,0,32),
|
||||
position = guiCoord(0,3,0,0),
|
||||
fontSize = 16,
|
||||
textAlpha = 0.5,
|
||||
text = "Nothing selected."
|
||||
}, "mainTopBar")
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local propertiesBtn = toolsController.createButton("windowsTab", "fa:s-sliders-h", "Properties")
|
||||
propertiesBtn:mouseLeftReleased(function ()
|
||||
controller.window.visible = not controller.window.visible
|
||||
end)
|
||||
end
|
||||
|
||||
local instanceEditing = nil
|
||||
local function callbackInput(property, value)
|
||||
if instanceEditing and instanceEditing[property] ~= nil then
|
||||
instanceEditing[property] = value
|
||||
end
|
||||
end
|
||||
|
||||
controller.parseInputs = {
|
||||
block = function (property, gui)
|
||||
|
||||
end,
|
||||
boolean = function (property, gui)
|
||||
callbackInput(property, gui.input.selected == true)
|
||||
end,
|
||||
number = function (property, gui)
|
||||
local num = tonumber(gui.input.text)
|
||||
if num then
|
||||
callbackInput(property, num)
|
||||
end
|
||||
end,
|
||||
string = function (property, gui)
|
||||
callbackInput(property, gui.input.text)
|
||||
end,
|
||||
vector3 = function(property, gui)
|
||||
local x,y,z = tonumber(gui.x.text),tonumber(gui.y.text),tonumber(gui.z.text)
|
||||
if x and y and z then
|
||||
callbackInput(property, vector3(x,y,z))
|
||||
end
|
||||
end,
|
||||
vector2 = function(property, gui)
|
||||
local x,y = tonumber(gui.x.text),tonumber(gui.y.text)
|
||||
if x and y then
|
||||
callbackInput(property, vector2(x,y))
|
||||
end
|
||||
end,
|
||||
colour = function(property, gui)
|
||||
local r,g,b = tonumber(gui.r.text),tonumber(gui.g.text),tonumber(gui.b.text)
|
||||
if r and g and b then
|
||||
callbackInput(property, colour(r,g,b))
|
||||
end
|
||||
end,
|
||||
quaternion = function(property, gui)
|
||||
--local x,y,z,w = tonumber(gui.x.text),tonumber(gui.y.text),tonumber(gui.z.text),tonumber(gui.w.text)
|
||||
local x,y,z = tonumber(gui.x.text),tonumber(gui.y.text),tonumber(gui.z.text)
|
||||
if x and y and z then
|
||||
callbackInput(property, quaternion():setEuler(math.rad(x),math.rad(y),math.rad(z)))
|
||||
end
|
||||
end,
|
||||
guiCoord = function(property, gui)
|
||||
local sx,ox,sy,oy = tonumber(gui.scaleX.text),tonumber(gui.offsetX.text),tonumber(gui.scaleY.text),tonumber(gui.offsetY.text)
|
||||
if sx and ox and sy and oy then
|
||||
callbackInput(property, guiCoord(sx,ox,sy,oy))
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
-- these methods are responsible for setting the propertie gui values when updated
|
||||
|
||||
controller.updateHandlers = {
|
||||
block = function (instance, gui, value)
|
||||
|
||||
end,
|
||||
boolean = function (instance, gui, value)
|
||||
gui.input.selected = value
|
||||
gui.input.text = gui.input.selected and "X" or " " -- temporary
|
||||
end,
|
||||
number = function (instance, gui, value)
|
||||
gui.input.text = tostring(value)
|
||||
end,
|
||||
string = function (instance, gui, value)
|
||||
gui.input.text = value
|
||||
end,
|
||||
vector3 = function(instance, gui, value)
|
||||
gui.x.text = string.format("%.3f", value.x)
|
||||
gui.y.text = string.format("%.3f", value.y)
|
||||
gui.z.text = string.format("%.3f", value.z)
|
||||
end,
|
||||
vector2 = function(instance, gui, value)
|
||||
gui.x.text = string.format("%.3f", value.x)
|
||||
gui.y.text = string.format("%.3f", value.y)
|
||||
end,
|
||||
colour = function(instance, gui, value)
|
||||
gui.r.text = string.format("%.5f", value.r)
|
||||
gui.g.text = string.format("%.5f", value.g)
|
||||
gui.b.text = string.format("%.5f", value.b)
|
||||
gui.col.backgroundColour = value
|
||||
end,
|
||||
quaternion = function(instance, gui, value)
|
||||
local euler = value:getEuler()
|
||||
gui.x.text = string.format("%.3f", math.deg(euler.x))
|
||||
gui.y.text = string.format("%.3f", math.deg(euler.y))
|
||||
gui.z.text = string.format("%.3f", math.deg(euler.z))
|
||||
--gui.w.text = tostring(value.w)
|
||||
end,
|
||||
guiCoord = function(instance, gui, value)
|
||||
gui.scaleX.text = tostring(value.scaleX)
|
||||
gui.offsetX.text = tostring(value.offsetX)
|
||||
gui.scaleY.text = tostring(value.scaleY)
|
||||
gui.offsetY.text = tostring(value.offsetY)
|
||||
end,
|
||||
}
|
||||
|
||||
controller.createInput = {
|
||||
default = function(instance, property, value)
|
||||
return uiController.create("guiFrame", nil, {
|
||||
backgroundAlpha = 0.25,
|
||||
name = "inputContainer",
|
||||
size = guiCoord(0.5, 0, 0, 20),
|
||||
position = guiCoord(0.5,0,0,0),
|
||||
cropChildren = false
|
||||
}, "secondary")
|
||||
end,
|
||||
|
||||
block = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = true,
|
||||
fontSize = 18,
|
||||
name = "input",
|
||||
size = guiCoord(1, -4, 1, -2),
|
||||
position = guiCoord(0, 2, 0, 1),
|
||||
text = "Instance Selector",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
boolean = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
local x = uiController.create("guiButton", container, {
|
||||
name = "input",
|
||||
size = guiCoord(0, 18, 1, -2),
|
||||
position = guiCoord(0, 2, 0, 1),
|
||||
text = "",
|
||||
backgroundAlpha = 0.75,
|
||||
align = enums.align.middle
|
||||
}, "light")
|
||||
|
||||
x:mouseLeftReleased(function ()
|
||||
x.selected = not x.selected
|
||||
x.text = x.selected and "X" or " " -- temporary
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end)
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
number = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "input",
|
||||
size = guiCoord(1, -4, 0, 18),
|
||||
position = guiCoord(0, 2, 0, 1),
|
||||
text = "0",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
x:textInput(function ()
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end)
|
||||
|
||||
if property == "type" and type(instance) == "light" then
|
||||
container.zIndex = 30 -- important because child elements need to be rendered above other properties!
|
||||
container.size = container.size + guiCoord(0,0,0,20)
|
||||
|
||||
|
||||
local presetSelect = uiController.create("guiTextBox", container, {
|
||||
size = guiCoord(1, -4, 0, 16),
|
||||
position = guiCoord(0, 2, 0, 23),
|
||||
borderRadius = 3,
|
||||
text = "Light Options",
|
||||
fontSize = 16,
|
||||
align = enums.align.middle,
|
||||
backgroundAlpha = 0.75
|
||||
}, "primary")
|
||||
|
||||
local optionsModal = uiController.create("guiFrame", container, {
|
||||
position = guiCoord(-0.8, 7, 0, 48),
|
||||
borderRadius = 6,
|
||||
visible = false,
|
||||
zIndex = 40,
|
||||
borderWidth = 1,
|
||||
cropChildren = false
|
||||
}, "main")
|
||||
|
||||
local isFocused = false
|
||||
local pendingHide = false
|
||||
local function queueCloseModal()
|
||||
if not pendingHide and optionsModal.visible then
|
||||
pendingHide = true
|
||||
wait(.4)
|
||||
if not isFocused then
|
||||
--still unfocused, lets hide.
|
||||
optionsModal.visible = false
|
||||
end
|
||||
pendingHide=false
|
||||
end
|
||||
end
|
||||
|
||||
presetSelect:mouseFocused(function ()
|
||||
optionsModal.visible = true
|
||||
isFocused = true
|
||||
end)
|
||||
|
||||
optionsModal:mouseFocused(function ()
|
||||
isFocused = true
|
||||
end)
|
||||
|
||||
presetSelect:mouseUnfocused(function ()
|
||||
isFocused = false
|
||||
queueCloseModal()
|
||||
end)
|
||||
|
||||
optionsModal:mouseUnfocused(function ()
|
||||
isFocused = false
|
||||
queueCloseModal()
|
||||
end)
|
||||
|
||||
uiController.create("guiImage", optionsModal, {
|
||||
size = guiCoord(0, 24, 0, 24),
|
||||
position = guiCoord(0.75, -12, 0, -15),
|
||||
handleEvents=false,
|
||||
zIndex = 10,
|
||||
backgroundAlpha = 0,
|
||||
texture = "fa:s-caret-up",
|
||||
imageColour = optionsModal.backgroundColour
|
||||
})
|
||||
|
||||
local curY = 0
|
||||
local curX = 0
|
||||
for lightType, num in pairs(enums.lightType) do
|
||||
|
||||
local btn = uiController.create("guiTextBox", optionsModal, {
|
||||
size = guiCoord(.5, -10, 0, 18),
|
||||
position = guiCoord(curX, 5, 0, curY + 4),
|
||||
borderRadius = 3,
|
||||
text = lightType,
|
||||
fontSize = 16,
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
btn:mouseFocused(function ()
|
||||
isFocused = true
|
||||
end)
|
||||
btn:mouseUnfocused(function ()
|
||||
isFocused = false
|
||||
queueCloseModal()
|
||||
end)
|
||||
btn:mouseLeftReleased(function ()
|
||||
x.text = tostring(num)
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end)
|
||||
|
||||
if curX == 0.5 then
|
||||
curY = curY + 24
|
||||
curX = 0
|
||||
else
|
||||
curX = 0.5
|
||||
end
|
||||
end
|
||||
|
||||
if curX == 0.5 then
|
||||
curY = curY + 24
|
||||
end
|
||||
|
||||
optionsModal.size = guiCoord(1.8, -10, 0, curY+4)
|
||||
|
||||
|
||||
end
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
scriptSource = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
local presetSelect = uiController.create("guiTextBox", container, {
|
||||
size = guiCoord(1, -4, 0, 16),
|
||||
position = guiCoord(0, 2, 0, 2),
|
||||
borderRadius = 3,
|
||||
text = "Edit Source",
|
||||
fontSize = 16,
|
||||
align = enums.align.middle,
|
||||
backgroundAlpha = 0.75
|
||||
}, "primary")
|
||||
presetSelect:mouseLeftReleased(function ()
|
||||
if instance[property] then
|
||||
instance[property]:editExternal()
|
||||
end
|
||||
end)
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
string = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "input",
|
||||
size = guiCoord(1, -4, 0, 18),
|
||||
position = guiCoord(0, 2, 0, 1),
|
||||
text = "text input",
|
||||
align = enums.align.middleLeft,
|
||||
zIndex = 2
|
||||
}, "primary")
|
||||
|
||||
x:textInput(function ()
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end)
|
||||
|
||||
-- TODO TODO TODO TODO
|
||||
-- We need some sort of helper function that'll make
|
||||
-- modals for situations like this:
|
||||
|
||||
if property == "mesh" then
|
||||
container.zIndex = 30 -- important because child elements need to be rendered above other properties!
|
||||
container.size = container.size + guiCoord(0,0,0,20)
|
||||
|
||||
|
||||
local presetSelect = uiController.create("guiTextBox", container, {
|
||||
size = guiCoord(1, -4, 0, 16),
|
||||
position = guiCoord(0, 2, 0, 23),
|
||||
borderRadius = 3,
|
||||
text = "Mesh Presets",
|
||||
fontSize = 16,
|
||||
align = enums.align.middle,
|
||||
backgroundAlpha = 0.75
|
||||
}, "primary")
|
||||
|
||||
local meshModal = uiController.create("guiFrame", container, {
|
||||
position = guiCoord(-0.8, 7, 0, 48),
|
||||
borderRadius = 6,
|
||||
visible = false,
|
||||
zIndex = 40,
|
||||
borderWidth = 1,
|
||||
cropChildren = false
|
||||
}, "main")
|
||||
|
||||
local isFocused = false
|
||||
local pendingHide = false
|
||||
local function queueCloseModal()
|
||||
if not pendingHide and meshModal.visible then
|
||||
pendingHide = true
|
||||
spawnThread(function ()
|
||||
-- Code here...
|
||||
wait(.4)
|
||||
if not isFocused then
|
||||
--still unfocused, lets hide.
|
||||
meshModal.visible = false
|
||||
end
|
||||
pendingHide=false
|
||||
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
presetSelect:onSync("mouseFocused", function ()
|
||||
meshModal.visible = true
|
||||
isFocused = true
|
||||
end)
|
||||
|
||||
meshModal:onSync("mouseFocused", function ()
|
||||
isFocused = true
|
||||
end)
|
||||
|
||||
presetSelect:onSync("mouseUnfocused", function ()
|
||||
isFocused = false
|
||||
queueCloseModal()
|
||||
end)
|
||||
|
||||
meshModal:onSync("mouseUnfocused", function ()
|
||||
isFocused = false
|
||||
queueCloseModal()
|
||||
end)
|
||||
|
||||
uiController.create("guiImage", meshModal, {
|
||||
size = guiCoord(0, 24, 0, 24),
|
||||
position = guiCoord(0.75, -12, 0, -15),
|
||||
handleEvents=false,
|
||||
zIndex = 10,
|
||||
backgroundAlpha = 0,
|
||||
texture = "fa:s-caret-up",
|
||||
imageColour = meshModal.backgroundColour
|
||||
})
|
||||
|
||||
local curY = 0
|
||||
local curX = 0
|
||||
for meshName, actualMeshName in pairs(meshShorcuts) do
|
||||
|
||||
local btn = uiController.create("guiTextBox", meshModal, {
|
||||
size = guiCoord(.5, -10, 0, 18),
|
||||
position = guiCoord(curX, 5, 0, curY + 4),
|
||||
borderRadius = 3,
|
||||
text = meshName,
|
||||
fontSize = 16,
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
btn:onSync("mouseFocused", function ()
|
||||
isFocused = true
|
||||
end)
|
||||
btn:onSync("mouseUnfocused", function ()
|
||||
isFocused = false
|
||||
queueCloseModal()
|
||||
end)
|
||||
btn:mouseLeftReleased(function ()
|
||||
x.text = actualMeshName
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end)
|
||||
|
||||
if curX == 0.5 then
|
||||
curY = curY + 24
|
||||
curX = 0
|
||||
else
|
||||
curX = 0.5
|
||||
end
|
||||
end
|
||||
|
||||
if curX == 0.5 then
|
||||
curY = curY + 24
|
||||
end
|
||||
|
||||
meshModal.size = guiCoord(1.8, -10, 0, curY+4)
|
||||
|
||||
|
||||
end
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
vector3 = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
container.size = guiCoord(container.size.scaleX, 0, 0, 60)
|
||||
|
||||
local xLabel = uiController.create("guiTextBox", container, {
|
||||
name = "labelX",
|
||||
size = guiCoord(0, 10, 1/3, -1),
|
||||
position = guiCoord(0,-10,0,1),
|
||||
fontSize = 16,
|
||||
textAlpha = 0.6,
|
||||
text = "X",
|
||||
align = enums.align.topLeft
|
||||
}, "mainText")
|
||||
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "x",
|
||||
size = guiCoord(1, -4, 1/3, -1),
|
||||
position = guiCoord(0, 2, 0, 0),
|
||||
text = "0",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
local yLabel = xLabel:clone()
|
||||
yLabel.name = "yLabel"
|
||||
yLabel.text = "Y"
|
||||
yLabel.parent = container
|
||||
yLabel.position = guiCoord(0, -10, 1/3, 1)
|
||||
themeController.add(yLabel, "mainText")
|
||||
|
||||
local y = x:clone()
|
||||
y.name = "y"
|
||||
y.parent = container
|
||||
y.position = guiCoord(0, 2, 1/3, 0)
|
||||
themeController.add(y, "primary")
|
||||
|
||||
local zLabel = xLabel:clone()
|
||||
zLabel.name = "zLabel"
|
||||
zLabel.text = "Z"
|
||||
zLabel.parent = container
|
||||
zLabel.position = guiCoord(0, -10, 2/3, 1)
|
||||
themeController.add(yLabel, "mainText")
|
||||
|
||||
local z = x:clone()
|
||||
z.name = "z"
|
||||
z.parent = container
|
||||
z.position = guiCoord(0, 2, 2/3, 0)
|
||||
themeController.add(z, "primary")
|
||||
|
||||
local function handler()
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end
|
||||
x:textInput(handler)
|
||||
y:textInput(handler)
|
||||
z:textInput(handler)
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
vector2 = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
container.size = guiCoord(container.size.scaleX, 0, 0, 40)
|
||||
|
||||
local xLabel = uiController.create("guiTextBox", container, {
|
||||
name = "labelX",
|
||||
size = guiCoord(0, 10, 1/2, -1),
|
||||
position = guiCoord(0,-10,0,2),
|
||||
fontSize = 16,
|
||||
textAlpha = 0.6,
|
||||
text = "X",
|
||||
align = enums.align.topLeft
|
||||
}, "mainText")
|
||||
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "x",
|
||||
size = guiCoord(0, -4, 1/2, -2),
|
||||
position = guiCoord(0, 2, 0, 1),
|
||||
text = "0",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
local yLabel = xLabel:clone()
|
||||
yLabel.name = "yLabel"
|
||||
yLabel.text = "Y"
|
||||
yLabel.parent = container
|
||||
yLabel.position = guiCoord(0, -10, 1/2, 2)
|
||||
themeController.add(yLabel, "mainText")
|
||||
|
||||
local y = x:clone()
|
||||
y.name = "y"
|
||||
y.parent = container
|
||||
y.position = guiCoord(0, 2, 1/2, 1)
|
||||
themeController.add(y, "primary")
|
||||
local function handler()
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end
|
||||
x:textInput(handler)
|
||||
y:textInput(handler)
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
quaternion = function(instance, property, value)
|
||||
|
||||
-- maybe quaternions need an Euler editor?
|
||||
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
container.size = guiCoord(container.size.scaleX, 0, 0, 60)
|
||||
|
||||
local xLabel = uiController.create("guiTextBox", container, {
|
||||
name = "labelX",
|
||||
size = guiCoord(0, 12, 1/3, -1),
|
||||
position = guiCoord(0,-10,0,1),
|
||||
fontSize = 16,
|
||||
textAlpha = 0.6,
|
||||
text = "X",
|
||||
align = enums.align.topLeft
|
||||
}, "mainText")
|
||||
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "x",
|
||||
size = guiCoord(1, -4, 1/3, -1),
|
||||
position = guiCoord(0, 2, 0, 0),
|
||||
text = "0",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
local yLabel = xLabel:clone()
|
||||
yLabel.name = "yLabel"
|
||||
yLabel.text = "Y"
|
||||
yLabel.parent = container
|
||||
yLabel.position = guiCoord(0, -10, 1/3, 1)
|
||||
themeController.add(yLabel, "mainText")
|
||||
|
||||
local y = x:clone()
|
||||
y.name = "y"
|
||||
y.parent = container
|
||||
y.position = guiCoord(0, 2, 1/3, 0)
|
||||
themeController.add(y, "primary")
|
||||
|
||||
local zLabel = xLabel:clone()
|
||||
zLabel.name = "zLabel"
|
||||
zLabel.text = "Z"
|
||||
zLabel.parent = container
|
||||
zLabel.position = guiCoord(0, -10, 2/3, 1)
|
||||
themeController.add(zLabel, "mainText")
|
||||
|
||||
local z = x:clone()
|
||||
z.name = "z"
|
||||
z.parent = container
|
||||
z.position = guiCoord(0, 2, 2/3, 0)
|
||||
themeController.add(z, "primary")
|
||||
|
||||
--[[local wLabel = xLabel:clone()
|
||||
wLabel.name = "wLabel"
|
||||
wLabel.text = "W"
|
||||
wLabel.parent = container
|
||||
wLabel.position = guiCoord(0, -12, 3/4, 2)
|
||||
themeController.add(wLabel, "mainText")
|
||||
|
||||
local w = x:clone()
|
||||
w.name = "w"
|
||||
w.parent = container
|
||||
w.position = guiCoord(0, 2, 3/4, 1)
|
||||
themeController.add(w, "primary")]]
|
||||
|
||||
local function handler()
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end
|
||||
x:textInput(handler)
|
||||
y:textInput(handler)
|
||||
z:textInput(handler)
|
||||
--w:textInput(handler)
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
guiCoord = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "scaleX",
|
||||
size = guiCoord(1/4, -4, 1, -2),
|
||||
position = guiCoord(0, 2, 0, 1),
|
||||
text = "0",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
local y = x:clone()
|
||||
y.name = "offsetX"
|
||||
y.parent = container
|
||||
y.position = guiCoord(1/4, 2, 0, 1)
|
||||
themeController.add(y, "primary")
|
||||
|
||||
local z = x:clone()
|
||||
z.name = "scaleY"
|
||||
z.parent = container
|
||||
z.position = guiCoord(1/2, 2, 0, 1)
|
||||
themeController.add(z, "primary")
|
||||
|
||||
local w = x:clone()
|
||||
w.name = "offsetY"
|
||||
w.parent = container
|
||||
w.position = guiCoord(3/4, 2, 0, 1)
|
||||
themeController.add(w, "primary")
|
||||
|
||||
local function handler()
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end
|
||||
x:textInput(handler)
|
||||
y:textInput(handler)
|
||||
z:textInput(handler)
|
||||
w:textInput(handler)
|
||||
|
||||
return container
|
||||
end,
|
||||
|
||||
colour = function(instance, property, value)
|
||||
local container = controller.createInput.default(value, pType, readOnly)
|
||||
container.size = guiCoord(container.size.scaleX, 0, 0, 60)
|
||||
|
||||
local rLabel = uiController.create("guiTextBox", container, {
|
||||
name = "labelR",
|
||||
size = guiCoord(0, 10, 1/3, -1),
|
||||
position = guiCoord(0,-10,0,2),
|
||||
fontSize = 16,
|
||||
textAlpha = 0.6,
|
||||
text = "R",
|
||||
align = enums.align.topLeft
|
||||
}, "mainText")
|
||||
|
||||
local x = uiController.create("guiTextBox", container, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "r",
|
||||
size = guiCoord(1, -24, 1/3, -2),
|
||||
position = guiCoord(0, 2, 0, 1),
|
||||
text = "1",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
local gLabel = rLabel:clone()
|
||||
gLabel.name = "gLabel"
|
||||
gLabel.text = "G"
|
||||
gLabel.parent = container
|
||||
gLabel.position = guiCoord(0, -10, 1/3, 1)
|
||||
themeController.add(gLabel, "mainText")
|
||||
|
||||
local g = x:clone()
|
||||
g.name = "g"
|
||||
g.parent = container
|
||||
g.position = guiCoord(0, 2, 1/3, 1)
|
||||
themeController.add(g, "primary")
|
||||
|
||||
local bLabel = rLabel:clone()
|
||||
bLabel.name = "bLabel"
|
||||
bLabel.text = "B"
|
||||
bLabel.parent = container
|
||||
bLabel.position = guiCoord(0, -10, 2/3, 1)
|
||||
themeController.add(bLabel, "mainText")
|
||||
|
||||
local b = x:clone()
|
||||
b.name = "b"
|
||||
b.parent = container
|
||||
b.position = guiCoord(0, 2, 2/3, 1)
|
||||
themeController.add(b, "primary")
|
||||
|
||||
local function handler()
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end
|
||||
x:textInput(handler)
|
||||
g:textInput(handler)
|
||||
b:textInput(handler)
|
||||
|
||||
local col = engine.construct("guiFrame", container, {
|
||||
name = "col",
|
||||
size = guiCoord(0, 14, 1, -2),
|
||||
position = guiCoord(1, -18, 0, 1),
|
||||
backgroundColour = colour(1,1,1),
|
||||
borderRadius = 2,
|
||||
})
|
||||
|
||||
col:mouseLeftReleased(function ()
|
||||
controller.colourPicker.window.visible = not controller.colourPicker.window.visible
|
||||
if controller.colourPicker.window.visible and instanceEditing and instanceEditing[property] then
|
||||
controller.colourPicker.setColour(instanceEditing[property])
|
||||
controller.colourPicker.setCallback(function (c)
|
||||
x.text = tostring(c.r)
|
||||
g.text = tostring(c.g)
|
||||
b.text = tostring(c.b)
|
||||
controller.parseInputs[type(value)](property, container)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
return container
|
||||
end,
|
||||
}
|
||||
|
||||
local function alphabeticalSorter(a, b)
|
||||
return a.property < b.property
|
||||
end
|
||||
|
||||
controller.eventHandlers = {}
|
||||
controller.instanceEditing = nil
|
||||
|
||||
function controller.generateProperties(instance)
|
||||
if instanceEditing == instance then return end
|
||||
|
||||
instanceEditing = nil
|
||||
controller.instanceEditing = nil
|
||||
|
||||
for i,v in pairs(controller.eventHandlers) do
|
||||
v:disconnect()
|
||||
end
|
||||
controller.eventHandlers = {}
|
||||
--controller.scrollView:destroyAllChildren()
|
||||
if instance then
|
||||
instanceEditing = instance
|
||||
controller.instanceEditing = instance
|
||||
|
||||
local members = controller.workshop:getMembersOfObject( instance )
|
||||
table.sort( members, alphabeticalSorter )
|
||||
|
||||
-- prototype teverse gui system isn't perfect,
|
||||
-- reuse already created instances to save time.
|
||||
|
||||
for _,v in pairs(controller.scrollView.children) do
|
||||
v.visible = false
|
||||
end
|
||||
|
||||
local y = 10
|
||||
local propertiesCount = 0
|
||||
|
||||
for i, v in pairs(members) do
|
||||
local value = instance[v.property]
|
||||
local pType = type(value)
|
||||
local readOnly = not v.writable
|
||||
|
||||
--letting the user turn physics off would cause raycasts to die.
|
||||
|
||||
if not readOnly and pType ~= "function" and v.property ~= "physics" and v.property ~= "doNotSerialise" and not controller.excludePropertyList[v.property] then
|
||||
propertiesCount = propertiesCount + 1
|
||||
local container = controller.scrollView["_" .. v.property .. pType]
|
||||
|
||||
if not container then
|
||||
container = engine.construct("guiFrame", controller.scrollView,
|
||||
{
|
||||
name = "_" .. v.property .. pType,
|
||||
backgroundAlpha = 0,
|
||||
size = guiCoord(1, -10, 0, 20),
|
||||
cropChildren = false
|
||||
})
|
||||
|
||||
label = uiController.create("guiTextBox", container, {
|
||||
name = "label",
|
||||
size = guiCoord(0.5, -15, 1, 0),
|
||||
position = guiCoord(0,0,0,0),
|
||||
fontSize = 18,
|
||||
text = v.property,
|
||||
align = enums.align.topRight
|
||||
}, "mainText")
|
||||
|
||||
local inputGui = nil
|
||||
|
||||
if controller.createInput[pType] then
|
||||
inputGui = controller.createInput[pType](instance, v.property, value)
|
||||
else
|
||||
inputGui = controller.createInput.default(instance, v.property, value)
|
||||
end
|
||||
|
||||
container.size = guiCoord(1, -10, 0, inputGui.size.offsetY)
|
||||
container.zIndex = inputGui.zIndex
|
||||
inputGui.parent = container
|
||||
else
|
||||
container.visible = true
|
||||
end
|
||||
|
||||
|
||||
if controller.updateHandlers[pType] then
|
||||
controller.updateHandlers[pType](instance, container.inputContainer, value)
|
||||
|
||||
end
|
||||
|
||||
container.position = guiCoord(0,5,0,y)
|
||||
|
||||
y = y + container.size.offsetY + 3
|
||||
end
|
||||
end
|
||||
|
||||
controller.info.text = type(instance) .. " has " .. tostring(propertiesCount) .. " visible members."
|
||||
|
||||
table.insert( controller.eventHandlers, instance:changed(function(prop, val)
|
||||
if controller.updateHandlers[type(val)] then
|
||||
local container = controller.scrollView["_" .. prop]
|
||||
if container then
|
||||
controller.updateHandlers[type(val)](instance, container.inputContainer, val)
|
||||
end
|
||||
end
|
||||
end))
|
||||
|
||||
local newSize = guiCoord(0,0,0,y)
|
||||
|
||||
if newSize ~= controller.scrollView.canvasSize then
|
||||
controller.scrollView.viewOffset = vector2(0,0)
|
||||
end
|
||||
|
||||
controller.scrollView.canvasSize = newSize
|
||||
else
|
||||
controller.info.text = "Nothing selected."
|
||||
end
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,159 +0,0 @@
|
|||
local controller = {}
|
||||
|
||||
local ui = require("tevgit:create/controllers/ui.lua")
|
||||
local selectionController = require("tevgit:create/controllers/select.lua")
|
||||
|
||||
-- displays a dialogue to user when they want to make a new container, asks them if they want to use an existing source or not.
|
||||
controller.newScriptDialogue = function(parent)
|
||||
if not parent or not parent.className then return end
|
||||
local backdrop = ui.create("guiFrame", ui.workshop.interface, {
|
||||
size = guiCoord(1, 0, 1, 0),
|
||||
backgroundAlpha = 0,
|
||||
zIndex = 2000
|
||||
}, "main")
|
||||
|
||||
engine.tween:begin(backdrop, 0.3, {backgroundAlpha = 0.7}, "inOutQuad")
|
||||
|
||||
local window = ui.create("guiFrame", backdrop, {
|
||||
size = guiCoord(0, 450, 0, 220),
|
||||
position = guiCoord(0.5, -225, 0.5, -110),
|
||||
backgroundAlpha = 0.5,
|
||||
borderRadius = 4
|
||||
}, "light")
|
||||
|
||||
engine.tween:begin(window, 0.3, {
|
||||
size = guiCoord(0, 400, 0, 174),
|
||||
position = guiCoord(0.5, -200, 0.5, -87),
|
||||
backgroundAlpha = 0.7,
|
||||
}, "inOutQuad")
|
||||
|
||||
local title = ui.create("guiTextBox", window, {
|
||||
size = guiCoord(1, -10, 0, 40),
|
||||
position = guiCoord(0, 5, 0, 10),
|
||||
text = "Choose a source for your new scriptContainer\nunder " .. (parent and parent.name or "?"),
|
||||
fontSize = 20,
|
||||
fontFile = "OpenSans-Bold.ttf",
|
||||
align = enums.align.middle,
|
||||
backgroundAlpha = 0
|
||||
}, "light")
|
||||
|
||||
local existingSource = engine.construct("guiFrame", window, {
|
||||
size = guiCoord(1/3, -4, 1, -56),
|
||||
position = guiCoord(0, 2, 0, 46),
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
ui.create("guiImage", existingSource, {
|
||||
size = guiCoord(0, 50, 0, 50),
|
||||
position = guiCoord(0.5, -25, 0.5, -25),
|
||||
backgroundAlpha = 0,
|
||||
texture = "fa:s-search",
|
||||
handleEvents = false
|
||||
}, "light")
|
||||
|
||||
ui.create("guiTextBox", existingSource, {
|
||||
size = guiCoord(1, -10, 0, 32),
|
||||
position = guiCoord(0, 5, 0.5, 25),
|
||||
backgroundAlpha = 0,
|
||||
fontSize = 16,
|
||||
text = "Existing\nSource {TODO!!!}",
|
||||
align = enums.align.topMiddle,
|
||||
handleEvents = false
|
||||
}, "light")
|
||||
|
||||
local newServer = engine.construct("guiFrame", window, {
|
||||
size = guiCoord(1/3, -4, 1, -56),
|
||||
position = guiCoord(1/3, 2, 0, 46),
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
ui.create("guiImage", newServer, {
|
||||
size = guiCoord(0, 50, 0, 50),
|
||||
position = guiCoord(0.5, -25, 0.5, -25),
|
||||
backgroundAlpha = 0,
|
||||
texture = "fa:s-server",
|
||||
handleEvents = false
|
||||
}, "light")
|
||||
|
||||
ui.create("guiTextBox", newServer, {
|
||||
size = guiCoord(1, -10, 0, 32),
|
||||
position = guiCoord(0, 5, 0.5, 25),
|
||||
backgroundAlpha = 0,
|
||||
fontSize = 16,
|
||||
text = "New Server\nSource",
|
||||
align = enums.align.topMiddle,
|
||||
handleEvents = false
|
||||
}, "light")
|
||||
|
||||
local newClient = engine.construct("guiFrame", window, {
|
||||
size = guiCoord(1/3, -4, 1, -56),
|
||||
position = guiCoord(2/3, 2, 0, 46),
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
ui.create("guiImage", newClient, {
|
||||
size = guiCoord(0, 50, 0, 50),
|
||||
position = guiCoord(0.5, -25, 0.5, -25),
|
||||
backgroundAlpha = 0,
|
||||
texture = "fa:s-laptop-code",
|
||||
handleEvents = false
|
||||
}, "light")
|
||||
|
||||
ui.create("guiTextBox", newClient, {
|
||||
size = guiCoord(1, -10, 0, 32),
|
||||
position = guiCoord(0, 5, 0.5, 25),
|
||||
backgroundAlpha = 0,
|
||||
fontSize = 16,
|
||||
text = "New Client\nSource",
|
||||
align = enums.align.topMiddle,
|
||||
handleEvents = false
|
||||
}, "light")
|
||||
|
||||
local keyListener = engine.input:keyPressed(function (inputObj)
|
||||
if inputObj.key == enums.key.escape then
|
||||
backdrop:destroy()
|
||||
end
|
||||
end)
|
||||
|
||||
backdrop:once("mouseLeftPressed", function ()
|
||||
backdrop:destroy()
|
||||
end)
|
||||
|
||||
backdrop:once("destroying", function ()
|
||||
keyListener:disconnect()
|
||||
end)
|
||||
|
||||
newClient:once("mouseLeftPressed", function ()
|
||||
local name = "newClientScript"
|
||||
local newSource = engine.construct("scriptSource", engine.assets.lua.client, {name = name.."Source"})
|
||||
local newScript = engine.construct("scriptContainer", parent, {name = name.."Container"})
|
||||
newScript.scriptType = enums.scriptType.client
|
||||
newScript.source = newSource
|
||||
selectionController.setSelection({newScript})
|
||||
wait(.4)
|
||||
backdrop:destroy()
|
||||
end)
|
||||
|
||||
newServer:once("mouseLeftPressed", function ()
|
||||
local name = "newServerScript"
|
||||
local newSource = engine.construct("scriptSource", engine.assets.lua.server, {name = name.."Source"})
|
||||
local newScript = engine.construct("scriptContainer", parent, {name = name.."Container"})
|
||||
newScript.scriptType = enums.scriptType.server
|
||||
newScript.source = newSource
|
||||
selectionController.setSelection({newScript})
|
||||
wait(.4)
|
||||
backdrop:destroy()
|
||||
end)
|
||||
end
|
||||
|
||||
controller.editScript = function (obj)
|
||||
-- Code here...
|
||||
if type(obj) == "scriptSource" then
|
||||
obj:editExternal()
|
||||
elseif obj.source then
|
||||
print(container)
|
||||
obj.source:editExternal()
|
||||
end
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,460 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- select.lua
|
||||
|
||||
local selectionController = {
|
||||
|
||||
selectable = true,
|
||||
clipboard = {},
|
||||
selection = {},
|
||||
boundingBoxListeners = {},
|
||||
|
||||
boundingBox = engine.construct("block", nil, {
|
||||
name = "_CreateMode_boundingBox",
|
||||
wireframe = true,
|
||||
castsShadows = false,
|
||||
static = true,
|
||||
physics = false,
|
||||
colour = colour(1, 0.8, 0.8),
|
||||
opacity = 0,
|
||||
size = vector3(0, 0, 0),
|
||||
doNotSerialise = true
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
local hotkeys = require("tevgit:create/controllers/hotkeys.lua")
|
||||
local contextMenu = require("tevgit:create/controllers/contextMenu.lua")
|
||||
local propertyEditor = require("tevgit:create/controllers/propertyEditor.lua")
|
||||
local lights = require("tevgit:create/controllers/lights.lua")
|
||||
local helpers = require("tevgit:create/helpers.lua")
|
||||
local history = require("tevgit:create/controllers/history.lua")
|
||||
|
||||
local isCalculating = false
|
||||
|
||||
local function clearSelectedObjectsInClipboard()
|
||||
for _, object in pairs(selectionController.selection) do
|
||||
for index, object2 in pairs(selectionController.clipboard) do
|
||||
if (object == object2) then
|
||||
selectionController.clipboard[index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function selectionController.copySelection()
|
||||
selectionController.clipboard = selectionController.selection
|
||||
end
|
||||
|
||||
function selectionController.pasteSelection(keepPosition)
|
||||
local selection = {}
|
||||
local clipboard = selectionController.clipboard
|
||||
local size, pos = selectionController.calculateBounding(clipboard)
|
||||
for _, object in pairs(clipboard) do
|
||||
if (object) then
|
||||
if (not helpers.startsWith(object.name, "_CreateMode_")) then
|
||||
history.addPoint(object, "HISTORY_CREATED")
|
||||
object.emissiveColour = colour()
|
||||
local clone = object:clone()
|
||||
clone.parent = workspace
|
||||
if (not keepPosition) then
|
||||
clone.position = object.position + vector3(0, size.y, 0)
|
||||
end
|
||||
table.insert(selection, clone)
|
||||
elseif (lights.lights[object]) then
|
||||
local light = lights.lights[object]
|
||||
history.addPoint(light, "HISTORY_CREATED")
|
||||
local clone = light:clone()
|
||||
clone.shadows = false
|
||||
clone.parent = workspace
|
||||
if (not keepPosition) then
|
||||
clone.position = light.position + vector3(0,1,0)
|
||||
else
|
||||
clone.position = light.position
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
selectionController.setSelection(selection)
|
||||
print("Pasted selection", selection)
|
||||
--[[for _,v in pairs(hotkeysController.clipboard) do
|
||||
if v and v.name ~= "_CreateMode_Light_Placeholder" then
|
||||
history.addPoint(v, "HISTORY_CREATED")
|
||||
v.emissiveColour = colour(0,0,0)
|
||||
local new = v:clone()
|
||||
new.parent = workspace
|
||||
new.position = v.position + vector3(0,size.y,0)
|
||||
table.insert(newItems, new)
|
||||
elseif v then
|
||||
--copying a light
|
||||
local light = require("tevgit:create/controllers/lights.lua").lights[v]
|
||||
if light then
|
||||
history.addPoint(light, "HISTORY_CREATED")
|
||||
local new = light:clone()
|
||||
new.shadows = false -- purely a performance boost.
|
||||
new.parent = workspace
|
||||
new.position = light.position + vector3(0,1,0)
|
||||
-- table.insert(newItems, new)
|
||||
end
|
||||
end
|
||||
end
|
||||
selectionController.setSelection(newItems)]]
|
||||
end
|
||||
|
||||
function selectionController.deleteSelection()
|
||||
local objects = selectionController.selection
|
||||
clearSelectedObjectsInClipboard()
|
||||
selectionController.setSelection({})
|
||||
if(objects[1].parent:isA("folder")) then
|
||||
history.addPoint(objects[1].parent, "HISTORY_DELETED")
|
||||
objects[1].parent:destroy()
|
||||
else
|
||||
for _, object in pairs(objects) do
|
||||
if (object) then
|
||||
history.addPoint(object, "HISTORY_DELETED")
|
||||
object:destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function selectionController.duplicateSelection()
|
||||
selectionController.copySelection()
|
||||
selectionController.pasteSelection(true)
|
||||
end
|
||||
|
||||
function selectionController.deselectSelection()
|
||||
selectionController.setSelection({})
|
||||
end
|
||||
|
||||
function selectionController.groupSelection()
|
||||
if (#selectionController.selection > 1) then
|
||||
local selection = selectionController.selection
|
||||
local folder = engine.folder("group")
|
||||
folder.parent = workspace
|
||||
for _, object in pairs(selection) do object.parent = folder end
|
||||
propertyEditor.generateProperties(folder)
|
||||
end
|
||||
end
|
||||
|
||||
function selectionController.ungroupSelection()
|
||||
if (#selectionController.selection > 1) then
|
||||
local parent = selectionController.selection[1].parent
|
||||
if (parent:isA("folder")) then
|
||||
for _, object in pairs(parent.children) do object.parent = parent.parent end
|
||||
propertyEditor.generateProperties(selectionController.selection[1])
|
||||
parent:destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function selectionController.removeBoundingListener(block)
|
||||
for i,v in pairs(selectionController.boundingBoxListeners) do
|
||||
if v[1] == block then
|
||||
selectionController.boundingBoxListeners[i] = nil
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function selectionController.addBoundingListener(block)
|
||||
table.insert(selectionController.boundingBoxListeners, { block, block:changed(selectionController.calculateBoundingBox) })
|
||||
end
|
||||
|
||||
function selectionController.calculateBounding(items)
|
||||
local min, max;
|
||||
for _,v in pairs(items) do
|
||||
if type(v) == "block" then
|
||||
if v and v.alive then
|
||||
if not min then min = v.position; max=v.position end
|
||||
local vertices = helpers.calculateVertices(v)
|
||||
for i,v in pairs(vertices) do
|
||||
min = min:min(v)
|
||||
max = max:max(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if max ~= nil and min ~= nil then
|
||||
return (max-min), (max - (max-min)/2)
|
||||
end
|
||||
end
|
||||
|
||||
function selectionController.calculateBoundingBox()
|
||||
if isCalculating then return end
|
||||
isCalculating = true
|
||||
|
||||
|
||||
if #selectionController.selection < 1 then
|
||||
selectionController.boundingBox.size = vector3(0,0,0)
|
||||
selectionController.boundingBox.opacity = 0
|
||||
isCalculating = false
|
||||
return
|
||||
end
|
||||
|
||||
selectionController.boundingBox.opacity = 0.5
|
||||
|
||||
local size, pos = selectionController.calculateBounding(selectionController.selection)
|
||||
if size and pos then
|
||||
selectionController.boundingBox.size = size
|
||||
selectionController.boundingBox.position = pos
|
||||
end
|
||||
|
||||
--engine.tween:begin(boundingBox, .025, {size = max-min, position = max - (max-min)/2}, "inQuad")
|
||||
|
||||
isCalculating = false
|
||||
end
|
||||
|
||||
function selectionController.setSelection(selection)
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
if type(v) == "block" then
|
||||
v.emissiveColour = colour(0.0, 0.0, 0.0)
|
||||
end
|
||||
end
|
||||
|
||||
for _,v in pairs(selectionController.boundingBoxListeners) do
|
||||
v[2]:disconnect()
|
||||
end
|
||||
selectionController.boundingBoxListeners = {}
|
||||
selectionController.selection = {}
|
||||
|
||||
for _,v in pairs(selection) do
|
||||
if type(v) == "block" then
|
||||
v.emissiveColour = colour(0.025, 0.025, 0.15)
|
||||
selectionController.addBoundingListener(v)
|
||||
end
|
||||
table.insert(selectionController.selection, v)
|
||||
end
|
||||
|
||||
if (#selection > 0) then
|
||||
propertyEditor.generateProperties(selection[1])
|
||||
end
|
||||
|
||||
selectionController.calculateBoundingBox()
|
||||
end
|
||||
|
||||
function selectionController.isSelected(object)
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
if v == object then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
engine.input:mouseLeftReleased(function(input)
|
||||
if not input.systemHandled and selectionController.selectable then
|
||||
local mouseHit = engine.physics:rayTestScreen(engine.input.mousePosition)
|
||||
if not mouseHit or mouseHit.object.workshopLocked then
|
||||
if mouseHit and mouseHit.object.name == "_CreateMode_" then return end -- dont deselect
|
||||
|
||||
-- User clicked empty space, deselect everything??#
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
if type(v) == "block" then
|
||||
if v and v.alive then
|
||||
v.emissiveColour = colour(0.0, 0.0, 0.0)
|
||||
else
|
||||
print("Cannot change emissiveColour: Object deleted.")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
selectionController.selection = {}
|
||||
|
||||
for _,v in pairs(selectionController.boundingBoxListeners) do
|
||||
v[2]:disconnect()
|
||||
end
|
||||
|
||||
selectionController.boundingBoxListeners = {}
|
||||
|
||||
selectionController.calculateBoundingBox()
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
local doSelect = true
|
||||
|
||||
if not engine.input:isKeyDown(enums.key.leftShift) then
|
||||
-- deselect everything that's already selected and move on
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
if type(v) == "block" then
|
||||
v.emissiveColour = colour(0.0, 0.0, 0.0)
|
||||
end
|
||||
end
|
||||
selectionController.selection = {}
|
||||
|
||||
for _,v in pairs(selectionController.boundingBoxListeners) do
|
||||
v[2]:disconnect()
|
||||
end
|
||||
selectionController.boundingBoxListeners = {}
|
||||
|
||||
selectionController.calculateBoundingBox()
|
||||
else
|
||||
for i,v in pairs(selectionController.selection) do
|
||||
if v == mouseHit.object then
|
||||
table.remove(selectionController.selection, i)
|
||||
selectionController.removeBoundingListener(v)
|
||||
v.emissiveColour = colour(0.0, 0.0, 0.0)
|
||||
doSelect = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if doSelect then
|
||||
|
||||
if (mouseHit.object.parent:isA("folder")) then
|
||||
selectionController.setSelection(mouseHit.object.parent.children)
|
||||
propertyEditor.generateProperties(mouseHit.object.parent)
|
||||
else
|
||||
if type(mouseHit.object) == "block" and mouseHit.object.name ~= "_CreateMode_Light_Placeholder" then
|
||||
mouseHit.object.emissiveColour = colour(0.025, 0.025, 0.15)
|
||||
end
|
||||
|
||||
table.insert(selectionController.selection, mouseHit.object)
|
||||
selectionController.addBoundingListener(mouseHit.object)
|
||||
selectionController.calculateBoundingBox()
|
||||
|
||||
if mouseHit and mouseHit.object.name == "_CreateMode_Light_Placeholder" then
|
||||
if lights.lights[mouseHit.object] then
|
||||
--ignore the block they pressed, they clicked a light
|
||||
propertyEditor.generateProperties(lights.lights[mouseHit.object])
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
propertyEditor.generateProperties(mouseHit.object)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
-- @hotkeys Copy, paste, & duplicate
|
||||
hotkeys:bind({ name = "copy", priorKey = enums.key.leftCtrl, key = enums.key.c, action =selectionController.copySelection })
|
||||
hotkeys:bind({ name = "paste", priorKey = enums.key.leftCtrl, key = enums.key.v, action =selectionController.pasteSelection })
|
||||
hotkeys:bind({ name = "duplicate", priorKey = enums.key.leftCtrl, key = enums.key.d, action =selectionController.duplicateSelection })
|
||||
|
||||
-- @hotkeys Delete, deselect, group & TBA ungroup
|
||||
hotkeys:bind({ name = "delete", key = enums.key.delete, action =selectionController.deleteSelection })
|
||||
hotkeys:bind({ name = "deselect", key = enums.key.escape, action = selectionController.deselectSelection })
|
||||
hotkeys:bind({ name = "group", priorKey = enums.key.leftCtrl, key = enums.key.g, action =selectionController.groupSelection })
|
||||
|
||||
-- @hotkey Focus selection
|
||||
local function focusSelection()
|
||||
if (#selectionController.selection > 0) then
|
||||
local mdn = vector3(helpers.median(selectionController.selection, "x"), helpers.median(selectionController.selection, "y"), helpers.median(selectionController.selection, "z") )
|
||||
engine.tween:begin(workspace.camera, .2, { position = mdn + (workspace.camera.rotation * vector3(0,0,1) * 15) }, "outQuad")
|
||||
end
|
||||
end
|
||||
hotkeys:bind({
|
||||
name = "focus on selection",
|
||||
key = enums.key.f,
|
||||
action = focusSelection
|
||||
})
|
||||
|
||||
-- @hotkey Select all
|
||||
hotkeys:bind({
|
||||
name = "select all",
|
||||
priorKey = enums.key.leftCtrl,
|
||||
key = enums.key.a,
|
||||
action = function()
|
||||
local selection = {}
|
||||
for _,v in pairs(workspace.children) do
|
||||
if not v.workshopLocked and type(v) == "block" then
|
||||
table.insert(selection, v)
|
||||
end
|
||||
end
|
||||
selectionController.setSelection(selection)
|
||||
end
|
||||
})
|
||||
|
||||
-- @section Context Menu
|
||||
local function newBlockWrapper(mesh)
|
||||
return function()
|
||||
local mousePos = engine.input.mousePosition
|
||||
local mouseHit = engine.physics:rayTestScreen(contextMenu.contextLastOpenedAt or mousePos)
|
||||
local block = engine.construct("block", workspace, {
|
||||
position = mouseHit.hitPosition,
|
||||
mesh = mesh
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local function newScript()
|
||||
return require("tevgit:create/controllers/scriptController.lua").newScriptDialogue(selectionController.selection[1])
|
||||
end
|
||||
|
||||
function selectionController.getContextOptions()
|
||||
local options = {
|
||||
new = {
|
||||
subOptions = {
|
||||
block = {
|
||||
action = newBlockWrapper()
|
||||
},
|
||||
sphere = {
|
||||
action = newBlockWrapper("primitive:sphere")
|
||||
},
|
||||
wedge = {
|
||||
action = newBlockWrapper("primitive:wedge")
|
||||
},
|
||||
script = {
|
||||
action = newScript
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (#selectionController.selection > 0) then
|
||||
options.copy = {
|
||||
hotkey = "ctrl + c",
|
||||
action = selectionController.copySelection
|
||||
}
|
||||
options.delete = {
|
||||
hotkey = "del",
|
||||
action = selectionController.deleteSelection
|
||||
}
|
||||
options.focus = {
|
||||
hotkey = "f",
|
||||
action = focusSelection
|
||||
}
|
||||
if (#selectionController.selection > 1) then
|
||||
if (selectionController.selection[1].parent:isA("folder")) then
|
||||
options.ungroup = {
|
||||
action = selectionController.ungroupSelection
|
||||
}
|
||||
else
|
||||
options.group = {
|
||||
hotkey = "ctrl + g",
|
||||
action = selectionController.groupSelection
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
if (#selectionController.clipboard > 0) then
|
||||
options.paste = {
|
||||
hotkey = "ctrl + v",
|
||||
action = selectionController.pasteSelection
|
||||
}
|
||||
options.duplicate = {
|
||||
hotkey = "ctrl + d",
|
||||
action = selectionController.duplicateSelection
|
||||
}
|
||||
end
|
||||
return options
|
||||
end
|
||||
|
||||
function selectionController.applyContext(object)
|
||||
--getContextOptions will be ran whenever we display a context menu for t his obj.
|
||||
return contextMenu.bind(object, selectionController.getContextOptions)
|
||||
end
|
||||
|
||||
engine.input:mouseRightPressed(function(input)
|
||||
wait(0.10)
|
||||
if ((not input.systemHandled) and (engine.physics:rayTestScreen(engine.input.mousePosition)) and (not engine.input:isMouseButtonDown(enums.mouseButton.right))) then
|
||||
contextMenu.display(contextMenu.create(selectionController.getContextOptions()))
|
||||
end
|
||||
end)
|
||||
|
||||
return selectionController
|
|
@ -1,59 +0,0 @@
|
|||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local selectionController = require("tevgit:create/controllers/select.lua")
|
||||
local propertyController = require("tevgit:create/controllers/propertyEditor.lua")
|
||||
local ui = require("tevgit:create/controllers/ui.lua")
|
||||
|
||||
local remoteTest = toolsController.createButton("topBar", "fa:s-globe", "Test")
|
||||
local db = false
|
||||
remoteTest:mouseLeftReleased(function ()
|
||||
if db then return end
|
||||
db = true
|
||||
local backdrop = ui.create("guiFrame", ui.workshop.interface, {
|
||||
size = guiCoord(1, 0, 1, 0),
|
||||
backgroundAlpha = 0,
|
||||
zIndex = 2000
|
||||
}, "main")
|
||||
|
||||
engine.tween:begin(backdrop, 0.3, {backgroundAlpha = 0.7}, "inOutQuad")
|
||||
|
||||
local window = ui.create("guiFrame", backdrop, {
|
||||
size = guiCoord(0, 450, 0, 60),
|
||||
position = guiCoord(0.5, -225, 0.5, -30),
|
||||
backgroundAlpha = 0.5,
|
||||
borderRadius = 4
|
||||
}, "light")
|
||||
|
||||
engine.tween:begin(window, 0.3, {
|
||||
size = guiCoord(0, 400, 0, 40),
|
||||
position = guiCoord(0.5, -200, 0.5, -20),
|
||||
backgroundAlpha = 0.7,
|
||||
}, "inOutQuad")
|
||||
|
||||
local title = ui.create("guiTextBox", window, {
|
||||
size = guiCoord(1, -10, 1, -10),
|
||||
position = guiCoord(0, 5, 0, 5),
|
||||
text = "Launching remote server...",
|
||||
fontSize = 20,
|
||||
fontFile = "OpenSans-Bold.ttf",
|
||||
align = enums.align.middle,
|
||||
backgroundAlpha = 0
|
||||
}, "light")
|
||||
|
||||
local loaded = false
|
||||
|
||||
spawnThread(function ()
|
||||
wait(5)
|
||||
if not loaded and title and title.alive then
|
||||
title.text = "This is taking a little longer than usual..."
|
||||
end
|
||||
end)
|
||||
|
||||
local success = ui.workshop:remoteTestServer(enums.serverLocation.london)
|
||||
loaded = true
|
||||
if not success then
|
||||
title.text = "Something went wrong?"
|
||||
wait(1)
|
||||
end
|
||||
|
||||
db = false
|
||||
end)
|
|
@ -1,138 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- theme.lua
|
||||
|
||||
local themeController = {}
|
||||
|
||||
print ("DEBUG: Loading theme.lua")
|
||||
|
||||
-- values from default are used in all styles unless overridden.
|
||||
-- theme names are probably gonna have to get made meaningful...
|
||||
themeController.darkTheme = {
|
||||
default = {
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
backgroundColour = colour:fromRGB(66, 66, 76),
|
||||
borderColour = colour:fromRGB(56, 56, 66),
|
||||
textColour = colour:fromRGB(255, 255, 255)
|
||||
},
|
||||
main = {
|
||||
backgroundColour = colour:fromRGB(66, 66, 76),
|
||||
textColour = colour:fromRGB(255, 255, 255),
|
||||
},
|
||||
mainText = {
|
||||
backgroundAlpha = 0, -- background
|
||||
textColour = colour:fromRGB(255, 255, 255),
|
||||
},
|
||||
mainTopBar = {
|
||||
backgroundColour = colour:fromRGB(45, 45, 55),
|
||||
textColour = colour:fromRGB(255, 255, 255),
|
||||
borderColour = colour:fromRGB(15, 15, 25)
|
||||
},
|
||||
secondary = {
|
||||
backgroundColour = colour:fromRGB(55, 55, 66),
|
||||
textColour = colour:fromRGB(255, 255, 255)
|
||||
},
|
||||
primary = {
|
||||
backgroundColour = colour:fromRGB(78, 83, 91),
|
||||
textColour = colour:fromRGB(255,255,255)
|
||||
},
|
||||
primaryText = {
|
||||
backgroundAlpha = 0,
|
||||
textColour = colour:fromRGB(255,255,255)
|
||||
},
|
||||
secondaryText = {
|
||||
backgroundAlpha = 0,
|
||||
textColour = colour:fromRGB(255, 255, 255),
|
||||
textAlpha = .5
|
||||
},
|
||||
light = {
|
||||
backgroundColour = colour:fromRGB(255,255,255),
|
||||
textColour = colour:fromRGB(66, 66, 76),
|
||||
imageColour = colour:fromRGB(66, 66, 76),
|
||||
borderColour = colour:fromRGB(245,245,245),
|
||||
},
|
||||
tools = {
|
||||
selected = colour:fromRGB(66, 134, 244),
|
||||
hovered = colour(0.9, 0.9, 0.9),
|
||||
deselected = colour(0.6, 0.6, 0.6)
|
||||
}
|
||||
}
|
||||
|
||||
themeController.lightTheme = {
|
||||
default = {
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
backgroundColour = colour:fromRGB(189, 195, 199),
|
||||
textColour = colour:fromRGB(0,0,0)
|
||||
},
|
||||
main = {
|
||||
backgroundColour = colour:fromRGB(189, 195, 199),
|
||||
textColour = colour:fromRGB(0,0,0),
|
||||
},
|
||||
mainText = {
|
||||
backgroundAlpha = 0,
|
||||
textColour = colour:fromRGB(0,0,0),
|
||||
},
|
||||
mainTopBar = {
|
||||
backgroundColour = colour:fromRGB(127, 140, 141),
|
||||
textColour = colour:fromRGB(0,0,0),
|
||||
},
|
||||
secondary = {
|
||||
backgroundColour = colour:fromRGB(149, 165, 166),
|
||||
textColour = colour:fromRGB(0,0,0)
|
||||
},
|
||||
primary = {
|
||||
backgroundColour = colour:fromRGB(52, 73, 94),
|
||||
textColour = colour:fromRGB(255,255,255)
|
||||
},
|
||||
light = {
|
||||
backgroundColour = colour:fromRGB(44, 62, 80),
|
||||
textColour = colour:fromRGB(255,255,255),
|
||||
},
|
||||
tools = {
|
||||
selected = colour:fromRGB(66, 134, 244),
|
||||
hovered = colour(0.9, 0.9, 0.9),
|
||||
deselected = colour(0.6, 0.6, 0.6)
|
||||
}
|
||||
}
|
||||
|
||||
themeController.currentTheme = themeController.darkTheme
|
||||
|
||||
themeController.guis = {} --make this a weak metatable (keys)
|
||||
|
||||
themeController.set = function(theme)
|
||||
themeController.currentTheme = theme
|
||||
for gui, style in pairs(themeController.guis) do
|
||||
themeController.applyTheme(gui)
|
||||
end
|
||||
end
|
||||
|
||||
themeController.applyTheme = function(gui)
|
||||
local styleName = themeController.guis[gui]
|
||||
|
||||
local style = themeController.currentTheme[styleName]
|
||||
if not style then
|
||||
style = {}
|
||||
end
|
||||
|
||||
if themeController.currentTheme["default"] then
|
||||
for property, value in pairs(themeController.currentTheme["default"]) do
|
||||
if not style[property] and gui[property] and gui[property] ~= value then --Chosen style does not have this property
|
||||
gui[property] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for property, value in pairs(style) do
|
||||
if gui[property] and gui[property] ~= value then
|
||||
gui[property] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
themeController.add = function(gui, style)
|
||||
--if themeController.guis[gui] then return end
|
||||
|
||||
themeController.guis[gui] = style
|
||||
themeController.applyTheme(gui)
|
||||
end
|
||||
|
||||
return themeController
|
|
@ -1,63 +0,0 @@
|
|||
local controller = {}
|
||||
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
|
||||
controller.window = nil
|
||||
controller.workshop = nil
|
||||
controller.scrollView = nil
|
||||
|
||||
function controller.createUI(workshop)
|
||||
controller.workshop = workshop
|
||||
controller.window = uiController.createWindow(workshop.interface, guiCoord(1, -400, 1, -50), guiCoord(0, 80, 0, 50), "Theme")
|
||||
controller.window.visible = false
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local themeSwitcherButton = toolsController.createButton("windowsTab", "fa:s-swatchbook", "Themes")
|
||||
themeSwitcherButton:mouseLeftReleased(function ()
|
||||
controller.window.visible = not controller.window.visible
|
||||
end)
|
||||
|
||||
local darkBtn = engine.construct("guiFrame", controller.window.content, {
|
||||
name = "input",
|
||||
size = guiCoord(0, 20, 0, 20),
|
||||
position = guiCoord(0, 5, 0, 5),
|
||||
text = "",
|
||||
backgroundAlpha = 0.75,
|
||||
backgroundColour = colour:fromRGB(66, 66, 76)
|
||||
})
|
||||
|
||||
local lightBtn = engine.construct("guiFrame", controller.window.content, {
|
||||
name = "input",
|
||||
size = guiCoord(0, 20, 0, 20),
|
||||
position = guiCoord(0, 30, 0, 5),
|
||||
text = "",
|
||||
backgroundAlpha = 0.75,
|
||||
backgroundColour = colour:fromRGB(200,200,200)
|
||||
})
|
||||
|
||||
local moreBtn = engine.construct("guiTextBox", controller.window.content, {
|
||||
name = "input",
|
||||
size = guiCoord(0, 20, 0, 20),
|
||||
position = guiCoord(0, 55, 0, 5),
|
||||
text = "+",
|
||||
backgroundAlpha = 0.75,
|
||||
backgroundColour = colour(1, 1, 1),
|
||||
textColour = colour(0, 0, 0),
|
||||
align = enums.align.middle
|
||||
})
|
||||
|
||||
darkBtn:mouseLeftReleased(function()
|
||||
themeController.set(themeController.darkTheme)
|
||||
end)
|
||||
|
||||
lightBtn:mouseLeftReleased(function()
|
||||
themeController.set(themeController.lightTheme)
|
||||
end)
|
||||
|
||||
moreBtn:mouseLeftReleased(function()
|
||||
print("Open main theme chooser!")
|
||||
end)
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,195 +0,0 @@
|
|||
--[[
|
||||
Copyright 2019 Teverse
|
||||
@File tool.lua
|
||||
@Author(s) Jay, Ly
|
||||
@Updated 5/8/19
|
||||
--]]
|
||||
|
||||
TOOL_BUTTON_SIZE = guiCoord(0, 30, 0, 30)
|
||||
TOOL_BUTTON_DEFAULT_POSITION = guiCoord(0, 8, 0, 8)
|
||||
TOOL_BUTTON_OFFSET = 45
|
||||
|
||||
local toolsController = {
|
||||
|
||||
currentToolId = 0,
|
||||
tools = {},
|
||||
|
||||
ui = nil,
|
||||
workshop = nil,
|
||||
container = nil
|
||||
}
|
||||
|
||||
-- Not sure if the following should be in this controller... Oh well.
|
||||
toolsController.menus = {}
|
||||
|
||||
-- You must create the gui before calling this function
|
||||
-- This function simply registers the menu to this controller.
|
||||
function toolsController.registerMenu(name, gui)
|
||||
if toolsController.menus[name] then
|
||||
return error("Menu already exists", 2)
|
||||
end
|
||||
|
||||
toolsController.menus[name] = {gui = gui, buttons = {}, currentX = 5, currentY = 0}
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Each button would be able to have their own size, and it is this controller's
|
||||
-- responsibility to position them properly.
|
||||
function toolsController.registerButton(name, gui)
|
||||
if not toolsController.menus[name] then
|
||||
return error("Menu doesn't exist", 2)
|
||||
end
|
||||
|
||||
table.insert(toolsController.menus[name], {gui=gui})
|
||||
|
||||
local menu = toolsController.menus[name]
|
||||
|
||||
gui.parent = menu.gui
|
||||
gui.position = guiCoord(0, menu.currentX, 0, menu.currentY)
|
||||
|
||||
local guiSize = gui.absoluteSize
|
||||
if menu.currentY + guiSize.y >= menu.gui.absoluteSize.y then
|
||||
menu.currentY = 0
|
||||
menu.currentX = menu.currentX + guiSize.x + 5
|
||||
else
|
||||
menu.currentY = menu.currentY + guiSize.y
|
||||
end
|
||||
end
|
||||
|
||||
-- Creates a button with an image and a label and registers it.
|
||||
-- height should be a decimal.
|
||||
function toolsController.createButton(menuName, image, label, height)
|
||||
if not height then height = 1 end
|
||||
local menu = toolsController.menus[menuName]
|
||||
local gui = toolsController.ui.createFrame(menu.gui, {size=guiCoord(0,55,height,0), hoverCursor = "fa:s-hand-pointer"}, "mainTopBar")
|
||||
if image then
|
||||
local imgSize = math.min(50, menu.gui.absoluteSize.y) - 5
|
||||
local img = toolsController.ui.create("guiImage", gui, {name = "image", size=guiCoord(0, (2/3) * imgSize, 0, (2/3) * imgSize), position=guiCoord(0.5, -((1/3) * imgSize),0,5), texture=image, handleEvents=false}, "mainTopBar")
|
||||
end
|
||||
local txt = toolsController.ui.create("guiTextBox", gui, {name = "text", size=guiCoord(1, 0, image and 1/3 or 1, -5), position=guiCoord(0,0,image and 2/3 or 0,0), text=label, fontSize=15, align=enums.align.middle, handleEvents=false}, "mainTopBar")
|
||||
toolsController.registerButton(menuName, gui)
|
||||
return gui
|
||||
end
|
||||
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
|
||||
local function onToolButtonMouseLeftReleased(toolId)
|
||||
|
||||
--[[
|
||||
@Description
|
||||
Manages toggling tools when a button is clicked
|
||||
|
||||
@Params
|
||||
Integer, toolId
|
||||
The unique # of the tool
|
||||
]]
|
||||
|
||||
if (toolsController.currentToolId > 0) then
|
||||
|
||||
-- @Note Deactive current tool in use
|
||||
local currentTool = toolsController.tools[toolsController.currentToolId]
|
||||
print("Debug: Deactivating tool " .. currentTool.name)
|
||||
currentTool.button.imageColour = themeController.currentTheme.tools.deselected
|
||||
currentTool.deactivated(currentTool.id)
|
||||
|
||||
end
|
||||
|
||||
if toolsController.currentToolId == toolId then
|
||||
|
||||
-- @Note Deselects tool {toolId}
|
||||
print("Debug: Deselecting tools")
|
||||
toolsController.currentToolId = 0
|
||||
|
||||
else
|
||||
|
||||
-- @Note Selects tool {toolId}
|
||||
toolsController.currentToolId = toolId
|
||||
local currentTool = toolsController.tools[toolsController.currentToolId]
|
||||
print("Debug: Activating tool " .. currentTool.name)
|
||||
currentTool.button.imageColour = themeController.currentTheme.tools.selected
|
||||
currentTool.activated(currentTool.id)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function toolsController:register(tool)
|
||||
|
||||
--[[
|
||||
@Description
|
||||
Registers a tool into the controller
|
||||
|
||||
@Params
|
||||
Dictionary, tool
|
||||
The given information about a {tool} including its functions
|
||||
@Model {
|
||||
|
||||
name = String,
|
||||
icon = String,
|
||||
description = String,
|
||||
data = [Dictionary],
|
||||
|
||||
activated = Function,
|
||||
deactivated = Functon,
|
||||
|
||||
}
|
||||
|
||||
@Returns
|
||||
Integer, toolId
|
||||
The resultant unique # of the tools that was registered
|
||||
]]
|
||||
|
||||
local toolId = #self.tools + 1
|
||||
|
||||
local toolButton = self.ui.create(
|
||||
"guiImage",
|
||||
self.container,
|
||||
{
|
||||
hoverCursor = "fa:s-hand-pointer",
|
||||
size = TOOL_BUTTON_SIZE,
|
||||
position = TOOL_BUTTON_DEFAULT_POSITION + guiCoord(0, 0, 0, TOOL_BUTTON_OFFSET * #self.tools),
|
||||
imageColour = themeController.currentTheme.tools.deselected,
|
||||
texture = tool.icon,
|
||||
backgroundAlpha = 0,
|
||||
},
|
||||
"main"
|
||||
)
|
||||
|
||||
if tool.hotKey then
|
||||
engine.input:keyPressed(function(inputObj)
|
||||
if inputObj.systemHandled then return end
|
||||
if inputObj.key == tool.hotKey then
|
||||
onToolButtonMouseLeftReleased(toolId)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
toolButton:mouseLeftReleased(function()
|
||||
onToolButtonMouseLeftReleased(toolId)
|
||||
end)
|
||||
|
||||
self.tools[toolId] = {
|
||||
|
||||
id = toolId,
|
||||
name = tool.name,
|
||||
|
||||
button = toolButton,
|
||||
hotKey = tool.hotKey,
|
||||
data = tool.data and tool.data or {},
|
||||
|
||||
activated = tool.activated,
|
||||
deactivated = tool.deactivated
|
||||
|
||||
}
|
||||
|
||||
local containerSize = self.container.size
|
||||
containerSize.scaleY = 0
|
||||
containerSize.offsetY = TOOL_BUTTON_OFFSET * #self.tools
|
||||
self.container.size = containerSize
|
||||
return toolId
|
||||
|
||||
end
|
||||
|
||||
return toolsController
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
--the purpose of this script is to unify all the tools
|
||||
--by allowing each one to access the same common settings
|
||||
--set by the user
|
||||
|
||||
local controller = {}
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
|
||||
controller.gridStep = 0.2
|
||||
controller.rotateStep = math.rad(9)
|
||||
controller.axis = {{"x", true},{"y", true},{"z", true}} -- should grid step be on .. axis
|
||||
|
||||
controller.window = nil
|
||||
controller.workshop = nil
|
||||
|
||||
function controller.createUI(workshop)
|
||||
controller.workshop = workshop
|
||||
controller.window = uiController.createWindow(workshop.interface, guiCoord(0, 66, 0, 100), guiCoord(0, 165, 0, 93), "Tool Settings")
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local settingsBtn = toolsController.createButton("windowsTab", "fa:s-cogs", "Settings")
|
||||
settingsBtn:mouseLeftReleased(function ()
|
||||
controller.window.visible = not controller.window.visible
|
||||
end)
|
||||
|
||||
local gridLabel = uiController.create("guiTextBox", controller.window.content, {
|
||||
size = guiCoord(0.6,-10,0,18),
|
||||
position = guiCoord(0,5,0,4),
|
||||
align = enums.align.middleRight,
|
||||
wrap = false,
|
||||
text = "Grid Step"
|
||||
}, "mainText")
|
||||
|
||||
local gridStepInput = uiController.create("guiTextBox", controller.window.content, {
|
||||
size = guiCoord(0.4,-10,0,18),
|
||||
position = guiCoord(0.6,5,0,4),
|
||||
readOnly = false,
|
||||
align = enums.align.middle,
|
||||
borderRadius = 5,
|
||||
text = tostring(controller.gridStep)
|
||||
}, "main")
|
||||
|
||||
gridStepInput:textInput(function ()
|
||||
local value = tonumber(gridStepInput.text)
|
||||
if value then
|
||||
controller.gridStep = value
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
local x = 5
|
||||
for i,v in pairs(controller.axis) do
|
||||
local gridAxisLabel = uiController.create("guiTextBox", controller.window.content, {
|
||||
size = guiCoord(0,20,0,18),
|
||||
position = guiCoord(0,x,0,28),
|
||||
borderRadius = 5,
|
||||
text = v[1] .. ":"
|
||||
}, "mainText")
|
||||
x=x+20
|
||||
local gridAxisInput = uiController.create("guiButton", controller.window.content, {
|
||||
size = guiCoord(0,18,0,18),
|
||||
position = guiCoord(0,x,0,28),
|
||||
align = enums.align.middle,
|
||||
text = v[2] and "X" or " ",
|
||||
selected = v[2]
|
||||
}, "main")
|
||||
gridAxisInput:mouseLeftReleased(function ()
|
||||
controller.axis[i][2] = not controller.axis[i][2]
|
||||
gridAxisInput.selected = controller.axis[i][2]
|
||||
gridAxisInput.text = gridAxisInput.selected and "X" or " "
|
||||
end)
|
||||
x=x+22
|
||||
end
|
||||
|
||||
|
||||
local rotateLabel = uiController.create("guiTextBox", controller.window.content, {
|
||||
size = guiCoord(0.6,-10,0,18),
|
||||
position = guiCoord(0,5,0,50),
|
||||
align = enums.align.middleRight,
|
||||
wrap = false,
|
||||
text = "Rotate Step"
|
||||
}, "mainText")
|
||||
|
||||
local rotateStepInput = uiController.create("guiTextBox", controller.window.content, {
|
||||
size = guiCoord(0.4,-10,0,18),
|
||||
position = guiCoord(0.6,5,0,50),
|
||||
readOnly = false,
|
||||
align = enums.align.middle,
|
||||
borderRadius = 5,
|
||||
text = tostring(math.deg(controller.rotateStep))
|
||||
}, "main")
|
||||
|
||||
rotateStepInput:textInput(function ()
|
||||
local value = math.rad(tonumber(gridStepInput.text))
|
||||
if value then
|
||||
controller.rotateStep = value
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,276 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- ui.lua
|
||||
|
||||
local uiController = {}
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local uiTabController = require("tevgit:create/controllers/uiTabController.lua")
|
||||
uiTabController.ui = uiController
|
||||
|
||||
local dockController = require("tevgit:create/controllers/dock.lua")
|
||||
dockController.ui = uiController
|
||||
|
||||
uiController.create = function(className, parent, properties, style)
|
||||
if not parent then parent = uiController.workshop.interface end
|
||||
local gui = engine.construct(className, parent, properties)
|
||||
themeController.add(gui, style and style or "default")
|
||||
return gui
|
||||
end
|
||||
|
||||
uiController.createFrame = function(parent, properties, style)
|
||||
if not parent then parent = uiController.workshop.interface end
|
||||
local gui = uiController.create("guiFrame", parent, properties, style)
|
||||
return gui
|
||||
end
|
||||
|
||||
uiController.createWindow = function(parent, pos, size, title, dontDock)
|
||||
if not parent then parent = uiController.workshop.interface end
|
||||
local container = engine.construct("guiFrame", parent, {
|
||||
name = "windowContainer",
|
||||
position = pos,
|
||||
size = size
|
||||
})
|
||||
|
||||
local titleBar = uiController.create("guiFrame", container, {
|
||||
name = "titleBar",
|
||||
size = guiCoord(1,0,0,22),
|
||||
hoverCursor = "fa:s-hand-pointer"
|
||||
}, "main")
|
||||
|
||||
local closeButton = uiController.create("guiImage", titleBar, {
|
||||
name = "Close",
|
||||
texture = "fa:s-times",
|
||||
position = guiCoord(1 , -20 ,0,3),
|
||||
hoverCursor = "fa:s-hand-pointer",
|
||||
size = guiCoord(0, 15, 0, 15),
|
||||
})
|
||||
closeButton:mouseLeftPressed(function ()
|
||||
container.visible = false
|
||||
end)
|
||||
|
||||
titleBar:mouseLeftPressed(function ()
|
||||
dockController.beginWindowDrag(container, dontDock)
|
||||
end)
|
||||
|
||||
|
||||
local textLabel = uiController.create("guiTextBox", titleBar, {
|
||||
name = "textLabel",
|
||||
size = guiCoord(1,-10,1,-2),
|
||||
position = guiCoord(0,5,0,0),
|
||||
text = title,
|
||||
handleEvents=false
|
||||
}, "mainText")
|
||||
|
||||
uiController.createFrame(titleBar, {
|
||||
name = "borderBottom",
|
||||
size = guiCoord(1, 0, 0, 2),
|
||||
position = guiCoord(0,0,1,-2)
|
||||
}, "secondary")
|
||||
|
||||
local content = uiController.create("guiFrame", container, {
|
||||
name = "content",
|
||||
position = guiCoord(0,0,0,22),
|
||||
size = guiCoord(1,0,1,-22)
|
||||
}, "mainTopBar")
|
||||
|
||||
return container
|
||||
end
|
||||
|
||||
local function spinCb()
|
||||
if not uiController.loadingFrame.visible then
|
||||
uiController.loadingTween.tweenObject.rotation = 0
|
||||
uiController.loadingTween:restart()
|
||||
end
|
||||
end
|
||||
|
||||
uiController.setLoading = function(loading, message)
|
||||
if not uiController.loadingFrame then return end
|
||||
if loading then
|
||||
uiController.loadingFrame.visible = true
|
||||
uiController.loadingFrame.loadingMessage.text = message and message or "Loading"
|
||||
spinCb()
|
||||
else
|
||||
uiController.loadingFrame.visible = false
|
||||
end
|
||||
end
|
||||
|
||||
uiController.createMainInterface = function(workshop)
|
||||
uiController.workshop = workshop
|
||||
uiController.loadingFrame = uiController.create("guiFrame", workshop.interface, {
|
||||
name = "loadingFrame",
|
||||
size = guiCoord(1,0,1,0),
|
||||
position = guiCoord(0,0,0,0),
|
||||
zIndex = 1000,
|
||||
}, "main")
|
||||
|
||||
uiController.create("guiTextBox", uiController.loadingFrame, {
|
||||
name = "loadingMessage",
|
||||
position = guiCoord(0, 10, 0.5, 0),
|
||||
size = guiCoord(1, -20, 0.5, -10),
|
||||
align = enums.align.topMiddle,
|
||||
fontSize = 21,
|
||||
backgroundAlpha = 0,
|
||||
text = "Please wait whilst Create Mode loads the latest assets."
|
||||
}, "main")
|
||||
|
||||
local loadingImage = uiController.create("guiImage", uiController.loadingFrame, {
|
||||
name = "loadingImage",
|
||||
position = guiCoord(0.5, -15, .333, -15),
|
||||
size = guiCoord(0, 30, 0, 30),
|
||||
texture = "fa:s-cog"
|
||||
}, "main")
|
||||
uiController.loadingTween = engine.tween:create(loadingImage, 1, {rotation = 360}, "inOutQuad", spinCb)
|
||||
|
||||
local sideBar = uiController.createFrame(workshop.interface, {
|
||||
name = "toolbars",
|
||||
size = guiCoord(0,46,1,0),
|
||||
position = guiCoord(0,10,0,100)
|
||||
}, "mainTopBar")
|
||||
|
||||
uiController.tabs = uiController.createFrame(workshop.interface, {
|
||||
name = "topbarTabs",
|
||||
size = guiCoord(1, 0, 0, 23),
|
||||
position = guiCoord(0,0,0,0)
|
||||
}, "main")
|
||||
|
||||
uiController.createFrame(uiController.tabs, {
|
||||
name = "borderBottom",
|
||||
size = guiCoord(1, 0, 0, 2),
|
||||
position = guiCoord(0,0,1,-2)
|
||||
}, "secondary")
|
||||
|
||||
uiController.topBar = uiController.createFrame(workshop.interface, {
|
||||
name = "topbar",
|
||||
size = guiCoord(1, 0, 0, 60),
|
||||
position = guiCoord(0,0,0,23)
|
||||
}, "mainTopBar")
|
||||
|
||||
uiController.windowsTab = uiController.createFrame(workshop.interface, {
|
||||
name = "windowsTab",
|
||||
size = guiCoord(1, 0, 0, 60),
|
||||
position = guiCoord(0,0,0,23)
|
||||
}, "mainTopBar")
|
||||
|
||||
uiController.createTab = uiController.createFrame(workshop.interface, {
|
||||
name = "createTab",
|
||||
size = guiCoord(1, 0, 0, 60),
|
||||
position = guiCoord(0,0,0,23)
|
||||
}, "mainTopBar")
|
||||
|
||||
|
||||
uiController.testingTab = uiController.createFrame(workshop.interface, {
|
||||
name = "testingTab",
|
||||
size = guiCoord(1, 0, 0, 60),
|
||||
position = guiCoord(0,0,0,23)
|
||||
}, "mainTopBar")
|
||||
|
||||
local tabController = uiTabController.registerTabs(uiController.tabs, "secondary", "main")
|
||||
uiTabController.createTab(uiController.tabs, "File", uiController.topBar)
|
||||
uiTabController.createTab(uiController.tabs, "Windows", uiController.windowsTab)
|
||||
uiTabController.createTab(uiController.tabs, "Create", uiController.createTab)
|
||||
uiTabController.createTab(uiController.tabs, "Testing", uiController.testingTab)
|
||||
|
||||
|
||||
toolsController.container = sideBar
|
||||
toolsController.workshop = workshop
|
||||
uiController.workshop = workshop
|
||||
uiController.theme = themeController
|
||||
toolsController.ui = uiController
|
||||
|
||||
toolsController.registerMenu("windowsTab", uiController.windowsTab)
|
||||
toolsController.registerMenu("createTab", uiController.createTab)
|
||||
toolsController.registerMenu("testingTab", uiController.testingTab)
|
||||
|
||||
--[[local darkmode = true
|
||||
toolsController.createButton("windowsTab", "fa:s-palette", "Switch themes"):mouseLeftReleased(function ()
|
||||
darkmode = not darkmode
|
||||
if not darkmode then
|
||||
themeController.set(themeController.lightTheme)
|
||||
else
|
||||
themeController.set(themeController.darkTheme)
|
||||
end
|
||||
end)]]
|
||||
|
||||
|
||||
toolsController.registerMenu("topBar", uiController.topBar)
|
||||
local saveBtn = toolsController.createButton("topBar", "fa:s-file-download", "Save")
|
||||
local saveAsBtn = toolsController.createButton("topBar", "fa:s-file-export", "Save As")
|
||||
local openBtn = toolsController.createButton("topBar", "fa:s-folder-open", "Open")
|
||||
local publishBtn = toolsController.createButton("topBar", "fa:s-cloud-upload-alt", "Publish")
|
||||
|
||||
publishBtn.image.backgroundAlpha = 0.45
|
||||
publishBtn.text.textAlpha = 0.45
|
||||
|
||||
--[[
|
||||
local function checkIfPublishable()
|
||||
settingsBar.btn.visible = (engine.workshop.gameFilePath ~= "")
|
||||
settingsBar.publishNote.text = (engine.workshop.gameFilePath == "" and "You need to save this game before publishing." or "This file isn't linked to the TevCloud.")
|
||||
settingsBar.btn.label.text = (engine.workshop.gameCloudId == "" and "Publish" or "Update")
|
||||
|
||||
if engine.workshop.gameCloudId ~= "" then
|
||||
settingsBar.publishNote.text = "This is a TevCloud project."
|
||||
end
|
||||
end
|
||||
|
||||
checkIfPublishable()
|
||||
engine.workshop:changed(checkIfPublishable)
|
||||
]]
|
||||
|
||||
saveBtn:mouseLeftReleased(function()
|
||||
workshop:saveGame()
|
||||
end)
|
||||
saveAsBtn:mouseLeftReleased(function()
|
||||
workshop:saveGameAsDialogue()
|
||||
end)
|
||||
openBtn:mouseLeftReleased(function()
|
||||
workshop:openFileDialogue()
|
||||
end)
|
||||
|
||||
uiController.publishStatus = uiController.createFrame(workshop.interface, {
|
||||
name = "publishStatus",
|
||||
size = guiCoord(0, 200, 0, 60),
|
||||
position = guiCoord(0.5, -100, 0.5, -30),
|
||||
borderRadius = 5,
|
||||
visible = false,
|
||||
}, "main")
|
||||
|
||||
uiController.create("guiTextBox", uiController.publishStatus, {
|
||||
name = "label",
|
||||
size = guiCoord(1, 0, 0, 24),
|
||||
position = guiCoord(0,0,0,4),
|
||||
align = enums.align.middle,
|
||||
text = "Publishing..."
|
||||
}, "main")
|
||||
|
||||
workshop:changed(function (p)
|
||||
if workshop.gameFilePath ~= "" then
|
||||
publishBtn.image.backgroundAlpha = 1
|
||||
publishBtn.text.textAlpha = 1
|
||||
else
|
||||
publishBtn.image.backgroundAlpha = 0.45
|
||||
publishBtn.text.textAlpha = 0.45
|
||||
end
|
||||
end)
|
||||
|
||||
workshop:published(function (success)
|
||||
if success then
|
||||
uiController.publishStatus.label.text = "Success! " .. workshop.gameCloudId
|
||||
wait(2)
|
||||
uiController.publishStatus.visible = false
|
||||
else
|
||||
uiController.publishStatus.label.text = "Failed"
|
||||
wait(2)
|
||||
uiController.publishStatus.visible = false
|
||||
end
|
||||
end)
|
||||
|
||||
publishBtn:mouseLeftReleased(function ()
|
||||
|
||||
uiController.publishStatus.visible = true
|
||||
uiController.publishStatus.label.text = "Publishing"
|
||||
workshop:publishDialogue()
|
||||
|
||||
end)
|
||||
end
|
||||
|
||||
return uiController
|
|
@ -1,56 +0,0 @@
|
|||
local controller = {}
|
||||
|
||||
local themeController = require("tevgit:create/controllers/theme.lua")
|
||||
controller.widgets = {}
|
||||
controller.ui = nil
|
||||
|
||||
function controller.registerTabs(container, selectedStyle, deselectedStyle)
|
||||
controller.widgets[container] = {
|
||||
selected = selectedStyle,
|
||||
deselected = deselectedStyle,
|
||||
tabs = {},
|
||||
active = true,
|
||||
currentX = 10
|
||||
}
|
||||
end
|
||||
|
||||
function controller.createTab(container, name, callback)
|
||||
if controller.widgets[container] then
|
||||
local active = controller.widgets[container].active
|
||||
controller.widgets[container].active = false
|
||||
|
||||
local btn = controller.ui.create("guiTextBox", container, {
|
||||
name = name,
|
||||
size = guiCoord(0, 50, 0, 18),
|
||||
position = guiCoord(0,controller.widgets[container].currentX,0,3),
|
||||
text = name,
|
||||
align = enums.align.middle,
|
||||
hoverCursor = "fa:s-hand-pointer",
|
||||
fontSize = 18,
|
||||
readOnly = true
|
||||
}, active and controller.widgets[container].selected or controller.widgets[container].deselected)
|
||||
|
||||
controller.widgets[container].tabs[btn] = callback
|
||||
local newX = math.min(130, btn.textDimensions.x + 40)
|
||||
btn.size = guiCoord(0, newX, 0, 18)
|
||||
controller.widgets[container].currentX = controller.widgets[container].currentX + newX + 10
|
||||
|
||||
if type(callback) ~= "function" and callback then
|
||||
-- callback not provided, assuming this was a gui passed, and that this controller should hide/show it
|
||||
callback.visible = active
|
||||
|
||||
btn:mouseLeftReleased(function ()
|
||||
controller.setTab(container, btn)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function controller.setTab(container, onBtn)
|
||||
for btn, cb in pairs(controller.widgets[container].tabs) do
|
||||
controller.widgets[container].tabs[btn].visible = (btn == onBtn)
|
||||
themeController.add(btn, (btn==onBtn) and controller.widgets[container].selected or controller.widgets[container].deselected)
|
||||
end
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,277 +0,0 @@
|
|||
local colourPicker = {}
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
|
||||
local hues = {
|
||||
colour(1,0,0),
|
||||
colour(1,0,1),
|
||||
colour(0,0,1),
|
||||
colour(0,1,1),
|
||||
colour(0,1,0),
|
||||
colour(1,1,0),
|
||||
colour(1,0,0),
|
||||
}
|
||||
|
||||
colourPicker.create = function()
|
||||
local window = uiController.createWindow(uiController.workshop.interface,
|
||||
guiCoord(0.5, -150, 0.5, -90),
|
||||
guiCoord(0, 300, 0, 180),
|
||||
"Colour Picker",
|
||||
true)
|
||||
local callback = nil
|
||||
|
||||
local startColour = colour(1,0,0)
|
||||
local currentColour = colour(1,0,0)
|
||||
|
||||
window.visible = true
|
||||
|
||||
|
||||
local colourPickerGradient = engine.construct("guiFrameMultiColour", window.content, {
|
||||
name = "square",
|
||||
size = guiCoord(0, 150, 0, 150),
|
||||
position = guiCoord(0, 5, 0, 5),
|
||||
topLeftColour = colour(1,1,1),
|
||||
topRightColour = startColour,
|
||||
bottomLeftColour = colour(1,1,1),
|
||||
bottomRightColour = startColour
|
||||
})
|
||||
|
||||
-- To have black on the bottom we need to overlay this...
|
||||
engine.construct("guiFrameMultiColour", colourPickerGradient, {
|
||||
name = "overlay",
|
||||
size = guiCoord(1,0,1,0),
|
||||
position = guiCoord(0, 0, 0, 0),
|
||||
|
||||
topLeftColour = colour(0,0,0),
|
||||
topLeftAlpha = 0,
|
||||
|
||||
topRightColour = colour(0,0,0),
|
||||
topRightAlpha = 0,
|
||||
|
||||
bottomLeftColour = colour(0,0,0),
|
||||
bottomLeftAlpha = 1,
|
||||
|
||||
bottomRightColour = colour(0,0,0),
|
||||
bottomRightAlpha = 1,
|
||||
|
||||
handleEvents = false
|
||||
})
|
||||
|
||||
local marker = engine.construct("guiFrame", colourPickerGradient, {
|
||||
name = "marker",
|
||||
size = guiCoord(0, 6, 0, 6),
|
||||
position = guiCoord(0, 0, 0, 0),
|
||||
handleEvents=false,
|
||||
backgroundColour = colour(1,1,1),
|
||||
borderColour = colour(0,0,0),
|
||||
zIndex = 10,
|
||||
borderWidth = 1,
|
||||
borderRadius = 6,
|
||||
borderAlpha = 1
|
||||
})
|
||||
|
||||
local hueBar = engine.construct("guiFrame", window.content, {
|
||||
name = "hueBar",
|
||||
size = guiCoord(0, 30, 1, -10),
|
||||
position = guiCoord(0, 160, 0, 5),
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
local hueBarMARKER = engine.construct("guiFrame", hueBar, {
|
||||
name = "hueBarMARKER",
|
||||
size = guiCoord(1, 0, 0, 1),
|
||||
position = guiCoord(0, 0, 0, 0),
|
||||
handleEvents=false,
|
||||
backgroundAlpha = 0,
|
||||
borderColour = colour(0,0,0),
|
||||
zIndex = 10,
|
||||
borderWidth = 2,
|
||||
borderAlpha = 1
|
||||
})
|
||||
|
||||
for i = 1, 6 do
|
||||
local colourPickerGradient = engine.construct("guiFrameMultiColour", hueBar, {
|
||||
handleEvents = false,
|
||||
size = guiCoord(1, 0, 1/6, 1),
|
||||
position = guiCoord(0, 0, (i-1)*(1/6), 0),
|
||||
topLeftColour = hues[i],
|
||||
topRightColour = hues[i],
|
||||
bottomLeftColour = hues[i+1],
|
||||
bottomRightColour = hues[i+1],
|
||||
handleEvents = false
|
||||
})
|
||||
end
|
||||
|
||||
local rLabel = uiController.create("guiTextBox", window.content, {
|
||||
name = "labelR",
|
||||
size = guiCoord(0, 20, 0, 16),
|
||||
position = guiCoord(0,200,0,5),
|
||||
fontSize = 16,
|
||||
textAlpha = 0.6,
|
||||
text = "R",
|
||||
align = enums.align.topLeft
|
||||
}, "mainText")
|
||||
|
||||
local rInput = uiController.create("guiTextBox", window.content, {
|
||||
backgroundAlpha = 0.25,
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
name = "r",
|
||||
size = guiCoord(1, -230, 0,16),
|
||||
position = guiCoord(0, 220, 0, 5),
|
||||
text = "1",
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
local gLabel = rLabel:clone()
|
||||
gLabel.name = "gLabel"
|
||||
gLabel.text = "G"
|
||||
gLabel.parent = window.content
|
||||
gLabel.position = guiCoord(0, 200, 0, 22)
|
||||
--themeController.add(gLabel, "mainText")
|
||||
|
||||
local g = rInput:clone()
|
||||
g.name = "g"
|
||||
g.parent = window.content
|
||||
g.position = guiCoord(0, 220, 0, 22)
|
||||
-- themeController.add(g, "primary")
|
||||
|
||||
local bLabel = rLabel:clone()
|
||||
bLabel.name = "bLabel"
|
||||
bLabel.text = "B"
|
||||
bLabel.parent = window.content
|
||||
bLabel.position = guiCoord(0, 200, 0, 39)
|
||||
--themeController.add(bLabel, "mainText")
|
||||
|
||||
local b = rInput:clone()
|
||||
b.name = "b"
|
||||
b.parent = window.content
|
||||
b.position = guiCoord(0, 220, 0, 39)
|
||||
|
||||
|
||||
local hexLabel = rLabel:clone()
|
||||
hexLabel.name = "hexLabel"
|
||||
hexLabel.text = "#"
|
||||
hexLabel.parent = window.content
|
||||
hexLabel.position = guiCoord(0, 200, 0, 55)
|
||||
--themeController.add(bLabel, "mainText")
|
||||
|
||||
local HEX = rInput:clone()
|
||||
HEX.name = "FFFFFF"
|
||||
HEX.parent = window.content
|
||||
HEX.position = guiCoord(0, 220, 0, 55)
|
||||
-- themeController.add(b, "primary")
|
||||
|
||||
local function handler()
|
||||
local newR = tonumber(rInput.text)
|
||||
local newG = tonumber(g.text)
|
||||
local newB = tonumber(b.text)
|
||||
if not newR or not newG or not newB then return end
|
||||
|
||||
local newColour = colour(newR, newG, newB)
|
||||
end
|
||||
rInput:textInput(handler)
|
||||
g:textInput(handler)
|
||||
b:textInput(handler)
|
||||
|
||||
hueBar:mouseLeftPressed(function ()
|
||||
while engine.input:isMouseButtonDown(enums.mouseButton.left) do
|
||||
local pos = engine.input.mousePosition - hueBar.absolutePosition
|
||||
local size = hueBar.absoluteSize
|
||||
|
||||
local y = pos.y/hueBar.absoluteSize.y
|
||||
|
||||
local sector = math.ceil(pos.y/(size.y * (1/6)))
|
||||
local hue = hues[sector]
|
||||
if hue and hues[sector+1] then
|
||||
|
||||
hueBarMARKER.position = guiCoord(0,0,y,0)
|
||||
|
||||
local selected = hue:lerp(hues[sector+1], (y - ((size.y * ((sector-1)/6))/hueBar.absoluteSize.y)) / (1/6))
|
||||
startColour = selected
|
||||
colourPickerGradient.topRightColour = startColour
|
||||
colourPickerGradient.bottomRightColour = startColour
|
||||
|
||||
local x = marker.absolutePosition.x/colourPickerGradient.absoluteSize.x
|
||||
local y = marker.absolutePosition.y/colourPickerGradient.absoluteSize.y
|
||||
|
||||
local selectedColour = startColour:lerp(colour(1,1,1), 1-x)
|
||||
selectedColour = selectedColour:lerp(colour(0,0,0), y)
|
||||
|
||||
window.content.backgroundColour = selectedColour
|
||||
|
||||
rInput.text = tostring(selectedColour.r*255)
|
||||
g.text = tostring(selectedColour.g*255)
|
||||
b.text = tostring(selectedColour.b*255)
|
||||
HEX.text = selectedColour:getHex()
|
||||
|
||||
if type(callback) == "function" and selectedColour ~= currentColour then
|
||||
callback(selectedColour)
|
||||
currentColour = selectedColour
|
||||
end
|
||||
end
|
||||
|
||||
wait()
|
||||
end
|
||||
end)
|
||||
|
||||
colourPickerGradient:mouseLeftPressed(function ()
|
||||
while engine.input:isMouseButtonDown(enums.mouseButton.left) do
|
||||
local pos = engine.input.mousePosition - colourPickerGradient.absolutePosition
|
||||
marker.position = guiCoord(0, pos.x+2, 0, pos.y-2)
|
||||
|
||||
local x = pos.x/colourPickerGradient.absoluteSize.x
|
||||
local y = pos.y/colourPickerGradient.absoluteSize.y
|
||||
|
||||
local selectedColour = startColour:lerp(colour(1,1,1), 1-x)
|
||||
selectedColour = selectedColour:lerp(colour(0,0,0), y)
|
||||
|
||||
window.content.backgroundColour = selectedColour
|
||||
|
||||
rInput.text = tostring(selectedColour.r*255)
|
||||
g.text = tostring(selectedColour.g*255)
|
||||
b.text = tostring(selectedColour.b*255)
|
||||
HEX.text = selectedColour:getHex()
|
||||
|
||||
if type(callback) == "function" and selectedColour ~= currentColour then
|
||||
callback(selectedColour)
|
||||
currentColour = selectedColour
|
||||
end
|
||||
|
||||
wait()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
return {
|
||||
window = window,
|
||||
setColour = function(c)
|
||||
local h,s,l = c:getHSL()
|
||||
h=h*360
|
||||
|
||||
local marker = math.ceil(h / 60)
|
||||
if marker <= 0 then marker = 1 end
|
||||
|
||||
local pos = hueBar.absolutePosition
|
||||
local size = hueBar.absoluteSize
|
||||
|
||||
local hue = hues[marker]
|
||||
|
||||
local selected = hue:lerp(hues[marker+1], ((h - (60*(marker-1)))/60))
|
||||
|
||||
startColour = selected
|
||||
colourPickerGradient.topRightColour = startColour
|
||||
colourPickerGradient.bottomRightColour = startColour
|
||||
|
||||
rInput.text = tostring(c.r*255)
|
||||
g.text = tostring(c.g*255)
|
||||
b.text = tostring(c.b*255)
|
||||
HEX.text = c:getHex()
|
||||
|
||||
hueBarMARKER.position = guiCoord(0,0,h/360,0)
|
||||
end,
|
||||
setCallback = function(c) callback = c end
|
||||
}
|
||||
end
|
||||
|
||||
return colourPicker
|
|
@ -1,91 +0,0 @@
|
|||
local controller = {}
|
||||
|
||||
function controller.roundToMultiple(number, multiple)
|
||||
if multiple == 0 then
|
||||
return number
|
||||
end
|
||||
|
||||
return ((number % multiple) > multiple/2) and number + multiple - number%multiple or number - number%multiple
|
||||
end
|
||||
|
||||
function controller.calculateVertices(block)
|
||||
local vertices = {}
|
||||
for x = -1,1,2 do
|
||||
for y = -1,1,2 do
|
||||
for z = -1,1,2 do
|
||||
table.insert(vertices, block.position + block.rotation* (vector3(x,y,z) *block.size/2))
|
||||
end
|
||||
end
|
||||
end
|
||||
return vertices
|
||||
end
|
||||
|
||||
-- these numbers are vertices indexes calculated in above function
|
||||
local faces = {
|
||||
{5, 6, 8, 7}, -- x forward,
|
||||
{1, 2, 4, 3}, -- x backward,
|
||||
{7, 8, 4, 3}, -- y upward,
|
||||
{5, 6, 2, 1}, -- y downward,
|
||||
{6, 2, 4, 8}, -- z forward
|
||||
{5, 1, 3, 7} -- z backward
|
||||
}
|
||||
|
||||
function controller.getCentreOfFace(block, face)
|
||||
local vertices = controller.calculateVertices(block)
|
||||
local avg = vector3(0,0,0)
|
||||
for _,i in pairs(faces[face]) do
|
||||
avg = avg + vertices[i]
|
||||
end
|
||||
|
||||
return avg/4
|
||||
end
|
||||
|
||||
function controller.vector3ToGuiCoord(vec)
|
||||
local inFrontOfCamera, screenPos = workspace.camera:worldToScreen(vec)
|
||||
if inFrontOfCamera then
|
||||
return guiCoord(0, screenPos.x, 0, screenPos.y)
|
||||
else
|
||||
return guiCoord(-1,0,0,0)
|
||||
end
|
||||
end
|
||||
|
||||
function controller.roundVectorToMultiple(vec, multiple)
|
||||
return vector3(controller.roundToMultiple(vec.x, multiple),
|
||||
controller.roundToMultiple(vec.y, multiple),
|
||||
controller.roundToMultiple(vec.z, multiple))
|
||||
end
|
||||
|
||||
function controller.roundVectorWithToolSettings(vec)
|
||||
local toolSettings = require("tevgit:create/controllers/toolSettings.lua")
|
||||
local multiple = toolSettings.gridStep
|
||||
vec.x = toolSettings.axis[1][2] and controller.roundToMultiple(vec.x, multiple) or vec.x
|
||||
vec.y = toolSettings.axis[2][2] and controller.roundToMultiple(vec.y, multiple) or vec.y
|
||||
vec.z = toolSettings.axis[3][2] and controller.roundToMultiple(vec.z, multiple) or vec.z
|
||||
return vec
|
||||
end
|
||||
|
||||
--Calculate median of vector
|
||||
--modified from http://lua-users.org/wiki/SimpleStats
|
||||
function controller.median(t, component)
|
||||
local temp={}
|
||||
|
||||
for k,v in pairs(t) do
|
||||
if v and v.position then
|
||||
table.insert(temp, v.position[component])
|
||||
end
|
||||
end
|
||||
|
||||
table.sort( temp )
|
||||
|
||||
if math.fmod(#temp,2) == 0 then
|
||||
return ( temp[#temp/2] + temp[(#temp/2)+1] ) / 2
|
||||
else
|
||||
return temp[math.ceil(#temp/2)]
|
||||
end
|
||||
end
|
||||
|
||||
function controller.startsWith(str, pat)
|
||||
return str:len(1, pat:len()) == pat
|
||||
end
|
||||
|
||||
return controller
|
|
@ -1,63 +0,0 @@
|
|||
-- Copyright (c) 2019 teverse.com
|
||||
-- main.lua
|
||||
return function(workshop)
|
||||
local controllers = {
|
||||
-- 1.0.0 has an internal console
|
||||
-- = require("tevgit:create/controllers/console.lua"),
|
||||
|
||||
selection = require("tevgit:create/controllers/select.lua"),
|
||||
theme = require("tevgit:create/controllers/theme.lua"),
|
||||
ui = require("tevgit:create/controllers/ui.lua"),
|
||||
camera = require("tevgit:create/controllers/camera.lua"),
|
||||
tool = require("tevgit:create/controllers/tool.lua"),
|
||||
property = require("tevgit:create/controllers/propertyEditor.lua"),
|
||||
hotkeys = require("tevgit:create/controllers/hotkeys.lua"),
|
||||
themeSwitcher = require("tevgit:create/controllers/themeSwitcher.lua"),
|
||||
history = require("tevgit:create/controllers/history.lua"),
|
||||
hierarchy = require("tevgit:create/controllers/hierarchy.lua")
|
||||
}
|
||||
|
||||
controllers.ui.createMainInterface(workshop)
|
||||
controllers.themeSwitcher.createUI(workshop)
|
||||
--controllers.console.createConsole(workshop)
|
||||
controllers.property.createUI(workshop)
|
||||
controllers.history.giveWorkshop(workshop)
|
||||
|
||||
controllers.hierarchy.createUI(workshop)
|
||||
|
||||
--loaded here due to dependencies
|
||||
controllers.env = require("tevgit:create/controllers/environment.lua")
|
||||
|
||||
controllers.toolSettings = require("tevgit:create/controllers/toolSettings.lua")
|
||||
controllers.toolSettings.createUI(workshop)
|
||||
|
||||
local tools = {
|
||||
add = require("tevgit:create/tools/add.lua"),
|
||||
select = require("tevgit:create/tools/select.lua"),
|
||||
move = require("tevgit:create/tools/move.lua"),
|
||||
resize = require("tevgit:create/tools/resize.lua"),
|
||||
rotate = require("tevgit:create/tools/rotate.lua"),
|
||||
-- commented as there's a stack overflow issue:
|
||||
--paint = require("tevgit:create/tools/paint.lua"),
|
||||
}
|
||||
|
||||
-- create default environment
|
||||
if workshop.gameFilePath == "" then
|
||||
controllers.env.setDefault()
|
||||
controllers.env.createStarterMap() -- Starter map, or the environment, may be overriden by teverse if the user is opening an existing .tev file.
|
||||
end
|
||||
wait(.3)
|
||||
collectgarbage()
|
||||
require("tevgit:create/controllers/dock.lua").loadSettings()
|
||||
require("tevgit:create/controllers/devtools.lua")
|
||||
require("tevgit:create/controllers/createTabController.lua")
|
||||
collectgarbage()
|
||||
controllers.ui.setLoading(false)
|
||||
|
||||
require("tevgit:create/controllers/scriptController.lua")
|
||||
require("tevgit:create/controllers/testing.lua")
|
||||
--wait(1)
|
||||
--scriptEditor = require("tevgit:create/scriptEditor/main.lua")
|
||||
|
||||
engine.sounds:play("tevurl:sound/sample.ogg")
|
||||
end
|
|
@ -1,438 +0,0 @@
|
|||
-- This script has been modified from https://github.com/LoganDark/lua-lexer
|
||||
-- The original license has been included:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- MIT License
|
||||
--
|
||||
-- Copyright (c) 2018 LoganDark
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all
|
||||
-- copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
-- SOFTWARE.
|
||||
local lexer = {}
|
||||
|
||||
function lookupify(src, list)
|
||||
list = list or {}
|
||||
|
||||
if type(src) == 'string' then
|
||||
for i = 1, src:len() do
|
||||
list[src:sub(i, i)] = true
|
||||
end
|
||||
elseif type(src) == 'table' then
|
||||
for i = 1, #src do
|
||||
list[src[i]] = true
|
||||
end
|
||||
end
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
local base_ident = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'
|
||||
local base_digits = '0123456789'
|
||||
local base_operators = '+-*/^%#'
|
||||
|
||||
local chars = {
|
||||
whitespace = lookupify(' \n\t\r'),
|
||||
validEscapes = lookupify('abfnrtv"\'\\'),
|
||||
ident = lookupify(
|
||||
base_ident .. base_digits,
|
||||
{
|
||||
start = lookupify(base_ident),
|
||||
}
|
||||
),
|
||||
|
||||
digits = lookupify(
|
||||
base_digits,
|
||||
{
|
||||
hex = lookupify(base_digits .. 'abcdefABCDEF')
|
||||
}
|
||||
),
|
||||
|
||||
symbols = lookupify(
|
||||
base_operators .. ',{}[]();.:', {
|
||||
equality = lookupify('~=><'),
|
||||
operators = lookupify(base_operators)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
local keywords = {
|
||||
structure = lookupify({
|
||||
'and', 'break', 'do', 'else', 'elseif', 'end', 'for', 'function',
|
||||
'goto', 'if', 'in', 'local', 'not', 'or', 'repeat', 'return', 'then',
|
||||
'until', 'while'
|
||||
}),
|
||||
|
||||
values = lookupify({
|
||||
'true', 'false', 'nil'
|
||||
})
|
||||
}
|
||||
|
||||
lexer.lex = function(text)
|
||||
local pos = 1
|
||||
local start = 1
|
||||
local buffer = {}
|
||||
local lines = {}
|
||||
|
||||
local function look(delta)
|
||||
delta = pos + (delta or 0)
|
||||
|
||||
return text:sub(delta, delta)
|
||||
end
|
||||
|
||||
local function get()
|
||||
pos = pos + 1
|
||||
|
||||
return look(-1)
|
||||
end
|
||||
|
||||
local function getDataLevel()
|
||||
local num = 0
|
||||
|
||||
while look(num) == '=' do
|
||||
num = num + 1
|
||||
end
|
||||
|
||||
if look(num) == '[' then
|
||||
pos = pos + num + 1
|
||||
|
||||
return num
|
||||
end
|
||||
end
|
||||
|
||||
local function getCurrentTokenText()
|
||||
return text:sub(start, pos - 1)
|
||||
end
|
||||
|
||||
local currentLineLength = 0
|
||||
local lineoffset = 0
|
||||
|
||||
local function pushToken(type, text)
|
||||
text = text or getCurrentTokenText()
|
||||
|
||||
local tk = buffer[#buffer]
|
||||
|
||||
if not tk or tk.type ~= type then
|
||||
tk = {
|
||||
type = type,
|
||||
data = text,
|
||||
posFirst = start - lineoffset,
|
||||
posLast = pos - 1 - lineoffset
|
||||
}
|
||||
|
||||
if tk.data ~= '' then
|
||||
buffer[#buffer + 1] = tk
|
||||
end
|
||||
else
|
||||
tk.data = tk.data .. text
|
||||
tk.posLast = tk.posLast + text:len()
|
||||
end
|
||||
|
||||
currentLineLength = currentLineLength + text:len()
|
||||
start = pos
|
||||
|
||||
return tk
|
||||
end
|
||||
|
||||
local function newline()
|
||||
lines[#lines + 1] = buffer
|
||||
buffer = {}
|
||||
|
||||
get()
|
||||
pushToken('newline')
|
||||
buffer[1] = nil
|
||||
|
||||
lineoffset = lineoffset + currentLineLength
|
||||
currentLineLength = 0
|
||||
end
|
||||
|
||||
local function getData(level, type)
|
||||
while true do
|
||||
local char = get()
|
||||
|
||||
if char == '' then
|
||||
return
|
||||
elseif char == '\n' then
|
||||
pos = pos - 1
|
||||
pushToken(type)
|
||||
newline()
|
||||
elseif char == ']' then
|
||||
local valid = true
|
||||
|
||||
for i = 1, level do
|
||||
if look() == '=' then
|
||||
pos = pos + 1
|
||||
else
|
||||
valid = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if valid and look() == ']' then
|
||||
pos = pos - level - 1
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function chompWhitespace()
|
||||
while true do
|
||||
local char = look()
|
||||
|
||||
if char == '\n' then
|
||||
pushToken('whitespace')
|
||||
newline()
|
||||
elseif chars.whitespace[char] then
|
||||
pos = pos + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
pushToken('whitespace')
|
||||
end
|
||||
|
||||
while true do
|
||||
chompWhitespace()
|
||||
|
||||
local char = get()
|
||||
|
||||
if char == '' then
|
||||
break
|
||||
elseif char == '-' and look() == '-' then
|
||||
pos = pos + 1
|
||||
|
||||
if look() == '[' then
|
||||
pos = pos + 1
|
||||
|
||||
local level = getDataLevel()
|
||||
|
||||
if level then
|
||||
getData(level, 'comment')
|
||||
|
||||
pos = pos + level + 2
|
||||
pushToken('comment')
|
||||
else
|
||||
while true do
|
||||
local char2 = get()
|
||||
|
||||
if char2 == '' or char2 == '\n' then
|
||||
pos = pos - 1
|
||||
pushToken('comment')
|
||||
|
||||
if char2 == '\n' then
|
||||
newline()
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
while true do
|
||||
local char2 = get()
|
||||
|
||||
if char2 == '' or char2 == '\n' then
|
||||
pos = pos - 1
|
||||
pushToken('comment')
|
||||
|
||||
if char2 == '\n' then
|
||||
newline()
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pushToken('comment')
|
||||
elseif char == '\'' or char == '"' then
|
||||
pushToken('string_start')
|
||||
|
||||
while true do
|
||||
local char2 = get()
|
||||
|
||||
if char2 == '\\' then
|
||||
pos = pos - 1
|
||||
pushToken('string')
|
||||
get()
|
||||
|
||||
local char3 = get()
|
||||
|
||||
if chars.digits[char3] then
|
||||
for i = 1, 2 do
|
||||
if chars.digits[look()] then
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
elseif char3 == 'x' then
|
||||
if chars.digits.hex[look()] and chars.digits.hex[look(1)] then
|
||||
pos = pos + 2
|
||||
else
|
||||
pushToken('unidentified')
|
||||
end
|
||||
elseif char3 == '\n' then
|
||||
pos = pos - 1
|
||||
pushToken('escape')
|
||||
newline()
|
||||
elseif not chars.validEscapes[char3] then
|
||||
pushToken('unidentified')
|
||||
end
|
||||
|
||||
pushToken('escape')
|
||||
elseif char2 == '\n' then
|
||||
pos = pos - 1
|
||||
pushToken('string')
|
||||
newline()
|
||||
|
||||
break
|
||||
elseif char2 == char or char2 == '' then
|
||||
pos = pos - 1
|
||||
pushToken('string')
|
||||
get()
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
pushToken('string_end')
|
||||
elseif chars.ident.start[char] then
|
||||
while chars.ident[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
local word = getCurrentTokenText()
|
||||
|
||||
if keywords.structure[word] then
|
||||
pushToken('keyword')
|
||||
elseif keywords.values[word] then
|
||||
pushToken('value')
|
||||
else
|
||||
pushToken('ident')
|
||||
end
|
||||
elseif chars.digits[char] or (char == '.' and chars.digits[look()]) then
|
||||
if char == '0' and look() == 'x' then
|
||||
pos = pos + 1
|
||||
|
||||
while chars.digits.hex[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
else
|
||||
while chars.digits[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
if look() == '.' then
|
||||
pos = pos + 1
|
||||
|
||||
while chars.digits[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
|
||||
if look():lower() == 'e' then
|
||||
pos = pos + 1
|
||||
|
||||
if look() == '-' then
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
while chars.digits[look()] do
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pushToken('number')
|
||||
elseif char == '[' then
|
||||
local level = getDataLevel()
|
||||
|
||||
if level then
|
||||
pushToken('string_start')
|
||||
|
||||
getData(level, 'string')
|
||||
pushToken('string')
|
||||
|
||||
pos = pos + level + 2
|
||||
pushToken('string_end')
|
||||
else
|
||||
pushToken('symbol')
|
||||
end
|
||||
elseif char == '.' then
|
||||
if look() == '.' then
|
||||
pos = pos + 1
|
||||
|
||||
if look() == '.' then
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
|
||||
if getCurrentTokenText():len() == 3 then
|
||||
pushToken('vararg')
|
||||
else
|
||||
pushToken('symbol')
|
||||
end
|
||||
elseif char == ':' and look() == ':' then
|
||||
get()
|
||||
|
||||
pushToken('label_start')
|
||||
|
||||
chompWhitespace()
|
||||
|
||||
if chars.ident.start[look()] then
|
||||
get()
|
||||
|
||||
while chars.ident[look()] do
|
||||
get()
|
||||
end
|
||||
|
||||
pushToken('label')
|
||||
|
||||
chompWhitespace()
|
||||
|
||||
if look() == ':' and look(1) == ':' then
|
||||
get()
|
||||
get()
|
||||
|
||||
pushToken('label_end')
|
||||
end
|
||||
end
|
||||
elseif chars.symbols.equality[char] then
|
||||
if look() == '=' then
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
pushToken('operator')
|
||||
elseif chars.symbols[char] then
|
||||
if chars.symbols.operators[char] then
|
||||
pushToken('operator')
|
||||
else
|
||||
pushToken('symbol')
|
||||
end
|
||||
else
|
||||
pushToken('unidentified')
|
||||
end
|
||||
end
|
||||
|
||||
lines[#lines + 1] = buffer
|
||||
|
||||
return lines
|
||||
end
|
||||
|
||||
return lexer;
|
|
@ -1,130 +0,0 @@
|
|||
-- very messy
|
||||
-- i dont know why i did some of this like this
|
||||
|
||||
|
||||
local lexer = require("tevgit:create/scriptEditor/lexer.lua")
|
||||
local scriptEditor = {}
|
||||
scriptEditor.mainFrame = engine.construct("guiFrame", engine.interface, {
|
||||
size=guiCoord(1, 0, 1, 0),
|
||||
backgroundColour=colour:fromRGB(40, 42, 54),
|
||||
handleEvents=false,
|
||||
zIndex=1002
|
||||
})
|
||||
|
||||
scriptEditor.colouredText = engine.construct("guiTextBox", scriptEditor.mainFrame, {
|
||||
size=guiCoord(1,-35,1,-10),
|
||||
position=guiCoord(0,30,0,5),
|
||||
zIndex=1003,
|
||||
align=enums.align.topLeft,
|
||||
fontFile = "FiraMono-Regular.ttf",
|
||||
fontSize=18,
|
||||
multiline=true,
|
||||
readOnly=true,
|
||||
wrapped = true,
|
||||
textAlpha=0.8,
|
||||
handleEvents = false,
|
||||
text = "",
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
scriptEditor.mainText = engine.construct("guiTextBox", scriptEditor.mainFrame, {
|
||||
size=guiCoord(1,-35,1,-10),
|
||||
position=guiCoord(0,30,0,5),
|
||||
zIndex=1002,
|
||||
align=enums.align.topLeft,
|
||||
fontFile = "FiraMono-Regular.ttf",
|
||||
fontSize=18,
|
||||
multiline=true,
|
||||
readOnly=false,
|
||||
wrapped = true,
|
||||
textAlpha=0.2,
|
||||
text = [[print("Hello Teverse!")]],
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
scriptEditor.colours = {
|
||||
background = colour:fromRGB(40, 42, 54),
|
||||
currentLine = colour:fromRGB(68, 71, 90),
|
||||
selection = colour:fromRGB(68, 71, 90),
|
||||
foreground = colour:fromRGB(248, 248, 242),
|
||||
|
||||
comment=colour:fromRGB(88,88,88),
|
||||
string_start=colour:fromRGB(241,250,140), --YELLOW
|
||||
string_end=colour:fromRGB(241,250,140),--yellow
|
||||
string=colour:fromRGB(241,250,140),--yellow
|
||||
escape=colour:fromRGB(189,147,249),--purple
|
||||
keyword=colour:fromRGB(255,121,198),--cyan
|
||||
value=colour:fromRGB(189,147,249),
|
||||
ident=colour:fromRGB(80,250,123),
|
||||
number=colour:fromRGB(189,147,249),
|
||||
symbol=colour:fromRGB(255,121,198), --PINK
|
||||
vararg=colour:fromRGB(255,184,108),
|
||||
operator=colour:fromRGB(255,121,198),
|
||||
label_start=colour:fromRGB(255, 184, 108),
|
||||
label_end=colour:fromRGB(255, 184, 108),
|
||||
label=colour:fromRGB(255, 184, 108),
|
||||
unidentified=colour(1,0,0)
|
||||
}
|
||||
|
||||
scriptEditor.lex = function()
|
||||
--scriptEditor.colouredText:setTextColour(scriptEditor.colours["default"])
|
||||
|
||||
--local curC = 0
|
||||
local text = scriptEditor.colouredText.text
|
||||
scriptEditor.colouredText.textColour = colour(0.5, 0.5, 0.5)
|
||||
--scriptEditor.colouredText.text = text
|
||||
--wait()
|
||||
--print(engine.lexer.lex, type(engine.lexer.lex))
|
||||
local lexxed = lexer.lex(text)
|
||||
local lineStart =0
|
||||
local lineText = ""
|
||||
|
||||
--print(lexxed, type(lexxed))
|
||||
for i, line in pairs(lexxed) do
|
||||
local thisLine = 0
|
||||
for t,v in pairs(line) do
|
||||
v.posFirst = v.posFirst -1
|
||||
|
||||
scriptEditor.colouredText:setTextColour(lineStart + v.posFirst, lineStart + v.posLast, scriptEditor.colours[v.type] and scriptEditor.colours[v.type] or colour(0.5,0.5,0.5))
|
||||
|
||||
-- curC = curC + len
|
||||
thisLine = v.posLast
|
||||
end
|
||||
lineStart = lineStart + thisLine + 1
|
||||
lineText = lineText .. (i-1) .."\n"
|
||||
end
|
||||
lineText = lineText .. "-"
|
||||
scriptEditor.leftText.text = lineText
|
||||
end
|
||||
|
||||
scriptEditor.mainText:changed(function (txt)
|
||||
scriptEditor.colouredText.text = scriptEditor.mainText.text .. "\n"
|
||||
scriptEditor.lex()
|
||||
end)
|
||||
|
||||
scriptEditor.leftFrame = engine.construct("guiFrame", scriptEditor.mainFrame, {
|
||||
size=guiCoord(0, 30, 1, 0),
|
||||
position=guiCoord(0, 0, 0, 0),
|
||||
backgroundColour=scriptEditor.colours.background,
|
||||
handleEvents=false,
|
||||
zIndex=1002
|
||||
})
|
||||
|
||||
|
||||
scriptEditor.leftText = engine.construct("guiTextBox", scriptEditor.leftFrame, {
|
||||
size=guiCoord(1,-10,1,-10),
|
||||
position=guiCoord(0,5,0,5),
|
||||
zIndex=1002,
|
||||
align=enums.align.topLeft,
|
||||
fontFile = "FiraMono-Regular.ttf",
|
||||
fontSize=18,
|
||||
multiline=true,
|
||||
textColour=scriptEditor.colours.comment,
|
||||
text = [[0]],
|
||||
backgroundAlpha = 0
|
||||
})
|
||||
|
||||
scriptEditor.lex()
|
||||
|
||||
|
||||
return scriptEditor
|
|
@ -1,318 +0,0 @@
|
|||
--[[
|
||||
Copyright 2019 Teverse
|
||||
@File add.lua
|
||||
@Author(s) Jay, Ly, joritochip
|
||||
@Updated 5/8/19
|
||||
--]]
|
||||
|
||||
-- TODO: Create a UI that allows the user to select what primitive to insert
|
||||
-- UI should also allow user to specify default values for the created primitives
|
||||
|
||||
TOOL_NAME = "Add"
|
||||
TOOL_ICON = "fa:s-plus-square"
|
||||
TOOL_DESCRIPTION = "Use this to insert shapes."
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local selectionController = require("tevgit:create/controllers/select.lua")
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
local propertyController = require("tevgit:create/controllers/propertyEditor.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 meshShortcuts = {
|
||||
cube = "primitive:cube",
|
||||
sphere = "primitive:sphere",
|
||||
cylinder = "primitive:cylinder",
|
||||
torus = "primitive:torus",
|
||||
cone = "primitive:cone",
|
||||
wedge = "primitive:wedge",
|
||||
corner = "primitive:corner",
|
||||
worker = "tevurl:3d/worker.glb",
|
||||
duck = "tevurl:3d/Duck.glb",
|
||||
avocado = "tevurl:3d/Avocado.glb",
|
||||
}
|
||||
|
||||
local toolIsActive
|
||||
|
||||
-- storing tool specific content in tool.data isn't really needed anymore due to modules...
|
||||
local placeholderBlock = engine.construct(
|
||||
"block",
|
||||
nil,
|
||||
{
|
||||
name = "createModeAddToolPlaceholderObject",
|
||||
size = vector3(1, 1, 1),
|
||||
static = true,
|
||||
opacity = 0.5,
|
||||
physics = false,
|
||||
workshopLocked=true,
|
||||
static=true,
|
||||
castsShadows = false,
|
||||
position = vector3(0, -100, 0)
|
||||
}
|
||||
)
|
||||
|
||||
local insertProps = {
|
||||
opacity = 1,
|
||||
castsShadows = true,
|
||||
name = "newBlock",
|
||||
static=true
|
||||
}
|
||||
|
||||
local configWindow = uiController.createWindow(uiController.workshop.interface, guiCoord(0, 66, 0, 203), guiCoord(0, 140, 0, 48), "Inserter")
|
||||
local editBtn = uiController.create("guiTextBox", configWindow.content, {
|
||||
size = guiCoord(1,-10,1,-10),
|
||||
position = guiCoord(0,5,0,5),
|
||||
align = enums.align.middle,
|
||||
text = "Edit Insertable"
|
||||
}, "main")
|
||||
|
||||
local meshWindow = uiController.createWindow(uiController.workshop.interface, guiCoord(0, 66, 0, 266), guiCoord(0, 175, 0, 22), "Presets")
|
||||
|
||||
local curY = 0
|
||||
local curX = 0
|
||||
local btnNum = 0
|
||||
for meshName, actualMeshName in pairs(meshShortcuts) do
|
||||
local btn = uiController.create("guiTextBox", meshWindow.content, {
|
||||
size = guiCoord(.5, -10, 0, 18),
|
||||
position = guiCoord(curX, 5, 0, curY + 8),
|
||||
borderRadius = 3,
|
||||
text = meshName,
|
||||
fontSize = 16,
|
||||
align = enums.align.middle
|
||||
}, "primary")
|
||||
|
||||
btn:mouseLeftReleased(function()
|
||||
placeholderBlock.mesh = actualMeshName
|
||||
end)
|
||||
|
||||
btnNum = btnNum + 1
|
||||
|
||||
if curX == 0.5 then
|
||||
curY = curY + 24
|
||||
curX = 0
|
||||
else
|
||||
curX = 0.5
|
||||
end
|
||||
end
|
||||
|
||||
local meshWindowY = (22 + (math.ceil(btnNum / 2) * 26))
|
||||
print(btnNum)
|
||||
print((math.ceil(btnNum / 2) * 26))
|
||||
print(meshWindowY)
|
||||
|
||||
meshWindow.size = guiCoord(0, 175, 0, meshWindowY)
|
||||
|
||||
local editing = false
|
||||
local db = false
|
||||
|
||||
editBtn:mouseLeftReleased(function ()
|
||||
if editing then editing = false return end
|
||||
if db then return end
|
||||
db = true
|
||||
|
||||
editing = true
|
||||
editBtn.text = "Back"
|
||||
|
||||
-- hide these from the property editor...
|
||||
propertyController.excludePropertyList = {
|
||||
["position"]=true,
|
||||
["workshopLocked"]=true,
|
||||
["name"]=true
|
||||
}
|
||||
|
||||
local wasPropertyEditing = propertyController.instanceEditing
|
||||
|
||||
propertyController.generateProperties(placeholderBlock)
|
||||
propertyController.window.visible = true
|
||||
|
||||
local startSize = propertyController.window.size
|
||||
local startPos = propertyController.window.position
|
||||
|
||||
engine.tween:begin(propertyController.window, 0.25, {position = guiCoord(2/3, 0, 0, 100), size = guiCoord(1/3, -10, 1, -110)}, "inOutQuad")
|
||||
|
||||
local camPos = workspace.camera.position
|
||||
local camRot = workspace.camera.rotation
|
||||
|
||||
placeholderBlock.position = vector3(0,-1000,0)
|
||||
for p,v in pairs(insertProps) do
|
||||
placeholderBlock[p] = v
|
||||
end
|
||||
|
||||
workspace.camera.position = vector3(-3,-1000,-20)
|
||||
workspace.camera:lookAt(vector3(-3,-999,0))
|
||||
|
||||
repeat
|
||||
wait()
|
||||
until propertyController.instanceEditing ~= placeholderBlock or not editing or not toolIsActive
|
||||
|
||||
for p,v in pairs(insertProps) do
|
||||
insertProps[p] = placeholderBlock[p]
|
||||
end
|
||||
|
||||
placeholderBlock.opacity = 0.5
|
||||
placeholderBlock.name = "createModeAddToolPlaceholderObject"
|
||||
placeholderBlock.castsShadows = false
|
||||
placeholderBlock.physics = false
|
||||
placeholderBlock.static = true
|
||||
placeholderBlock.workshopLocked = true
|
||||
|
||||
workspace.camera.position = camPos
|
||||
workspace.camera.rotation = camRot
|
||||
|
||||
engine.tween:begin(propertyController.window, 0.25, {position = startPos, size = startSize}, "inOutQuad")
|
||||
wait(0.3)
|
||||
|
||||
propertyController.excludePropertyList = {}
|
||||
if wasPropertyEditing then
|
||||
propertyController.generateProperties(wasPropertyEditing)
|
||||
end
|
||||
|
||||
editing = false
|
||||
db=false
|
||||
editBtn.text = "Edit Insertable"
|
||||
|
||||
end)
|
||||
|
||||
configWindow.visible = false
|
||||
meshWindow.visible = false
|
||||
|
||||
local function onToolActivated(toolId)
|
||||
configWindow.visible = true
|
||||
meshWindow.visible = true
|
||||
|
||||
--[[
|
||||
@Description
|
||||
Initializes the process (making placeholders & events) for placing blocks
|
||||
|
||||
@Params
|
||||
Integer, toolId
|
||||
The unique {toolId} given after registering the tool
|
||||
]]
|
||||
|
||||
selectionController.selectable = false
|
||||
toolIsActive = true
|
||||
|
||||
local tool = toolsController.tools[toolId]
|
||||
local mouseDown = 0
|
||||
|
||||
|
||||
--[[tool.data.placeholderBlock = engine.construct(
|
||||
"block",
|
||||
nil,
|
||||
{
|
||||
name = "createModeAddToolPlaceholderObject",
|
||||
size = vector3(1, 1, 1),
|
||||
static = true,
|
||||
opacity = 0.5,
|
||||
physics = false,
|
||||
castsShadows = false
|
||||
}
|
||||
)]]
|
||||
|
||||
local lastInsertPosition = vector3(0.1,12,04)
|
||||
local function placeBlock()
|
||||
if lastInsertPosition ~= placeholderBlock.position then
|
||||
lastInsertPosition = placeholderBlock.position:clone()
|
||||
local newBlock = placeholderBlock:clone()
|
||||
newBlock.workshopLocked = false
|
||||
newBlock.physics = true
|
||||
newBlock.parent = engine.workspace
|
||||
|
||||
for p,v in pairs(insertProps) do
|
||||
newBlock[p] = v
|
||||
end
|
||||
|
||||
propertyController.generateProperties(newBlock)
|
||||
selectionController.setSelection({newBlock})
|
||||
|
||||
-- Add this action to the history (Undo list)
|
||||
history.addPoint(newBlock, "HISTORY_CREATED")
|
||||
end
|
||||
end
|
||||
|
||||
tool.data.mouseDownEvent = engine.input:mouseLeftPressed(function(input)
|
||||
if input.systemHandled then return end
|
||||
placeBlock()
|
||||
local curTime = os.clock()
|
||||
mouseDown = curTime
|
||||
wait(1)
|
||||
if (mouseDown == curTime) then
|
||||
while (wait(.05)) and (mouseDown == curTime and toolsController.currentToolId == toolId) do
|
||||
placeBlock()
|
||||
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
tool.data.mouseUpEvent = engine.input:mouseLeftReleased(function(input)
|
||||
if input.systemHandled then return end
|
||||
|
||||
mouseDown = 0
|
||||
end)
|
||||
|
||||
tool.data.keyPressedEvent = engine.input:keyPressed(function(input)
|
||||
if input.systemHandled then return end
|
||||
|
||||
if input.key == enums.key.r then
|
||||
placeholderBlock.rotation = placeholderBlock.rotation * quaternion:setEuler(0,math.rad(45),0)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
while (toolIsActive and wait() and placeholderBlock) do
|
||||
if not editing then
|
||||
local mouseHit = engine.physics:rayTestScreenAllHits(engine.input.mousePosition, placeholderBlock)
|
||||
if #mouseHit > 0 then
|
||||
placeholderBlock.position = helpers.roundVectorWithToolSettings(mouseHit[1].hitPosition + vector3(0, 0.5, 0))
|
||||
end
|
||||
end
|
||||
end
|
||||
placeholderBlock.position = vector3(0,-10000,0) --lol
|
||||
end
|
||||
|
||||
local function onToolDeactivated(toolId)
|
||||
|
||||
configWindow.visible = false
|
||||
meshWindow.visible = false
|
||||
|
||||
--[[
|
||||
@Description
|
||||
Clears up any loose ends during deactivation
|
||||
|
||||
@Params
|
||||
Integer, toolId
|
||||
The unique {toolId} given after registering the tool
|
||||
]]
|
||||
toolIsActive = false
|
||||
selectionController.selectable = true
|
||||
local tool = toolsController.tools[toolId]
|
||||
|
||||
tool.data.mouseDownEvent:disconnect()
|
||||
tool.data.mouseDownEvent = nil
|
||||
tool.data.mouseUpEvent:disconnect()
|
||||
tool.data.mouseUpEvent = nil
|
||||
tool.data.keyPressedEvent:disconnect()
|
||||
tool.data.keyPressedEvent = nil
|
||||
|
||||
--tool.data.placeholderBlock:destroy()
|
||||
--tool.data.placeholderBlock = nil
|
||||
placeholderBlock.position = vector3(0,-10000,0) --lol
|
||||
placeholderBlock.static = true
|
||||
placeholderBlock.physics = false
|
||||
end
|
||||
|
||||
return toolsController:register({
|
||||
|
||||
name = TOOL_NAME,
|
||||
icon = TOOL_ICON,
|
||||
description = TOOL_DESCRIPTION,
|
||||
|
||||
hotKey = enums.key.number1,
|
||||
|
||||
activated = onToolActivated,
|
||||
deactivated = onToolDeactivated
|
||||
|
||||
})
|
||||
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
--[[
|
||||
This file remains here for reference.
|
||||
This tool behaves as a move tool that operates on the local axes.
|
||||
|
||||
It was being modified for the scale too.
|
||||
--]]
|
||||
|
||||
return error("bad.")
|
||||
TOOL_NAME = "Resize"
|
||||
TOOL_ICON = "fa:s-expand-arrows-alt"
|
||||
TOOL_DESCRIPTION = "Use this to resize primitives."
|
||||
|
||||
|
||||
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 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
|
||||
|
||||
-- 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,
|
||||
doNotSerialise=true,
|
||||
opacity = 0,
|
||||
renderQueue=1,
|
||||
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
|
||||
})
|
||||
|
||||
handle:mouseLeftPressed(function()
|
||||
if leftButtonDown then return end -- how
|
||||
|
||||
leftButtonDown = handle
|
||||
|
||||
selectionController.selectable = false
|
||||
gridGuideline.size = vector3(300, 0.1, 300)
|
||||
gridGuideline.rotation = handle.rotation
|
||||
gridGuideline.opacity = 0.5
|
||||
gridGuideline.position = handle.position
|
||||
|
||||
|
||||
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 = {}
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
mouseoffsets[v] = (mouseHit.hitPosition - v.position)
|
||||
end
|
||||
|
||||
local lastHit = mouseHit.hitPosition
|
||||
|
||||
local gridStep = toolSettings.gridStep
|
||||
|
||||
repeat
|
||||
if toolsController.currentToolId == toolId then
|
||||
--Face camera on one Axis
|
||||
--gridGuideline.position = handle.position
|
||||
--gridGuideline.rotation = handle.rotation
|
||||
|
||||
if component == "y" then
|
||||
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
|
||||
local moved = lastHit - target
|
||||
lastHit = target
|
||||
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
if mouseoffsets[v] then
|
||||
local newPos = target - mouseoffsets[v]
|
||||
local pos = v.position
|
||||
|
||||
if component == "y" then
|
||||
if gridStep > 0 and toolSettings.axis[2][2] then
|
||||
pos.y = helpers.roundToMultiple(newPos.y, gridStep)
|
||||
else
|
||||
pos.y = newPos.y
|
||||
end
|
||||
else
|
||||
|
||||
if gridStep > 0 and toolSettings.axis[1][2] then
|
||||
pos.x = helpers.roundToMultiple(newPos.x, gridStep)
|
||||
else
|
||||
pos.x = newPos.x
|
||||
end
|
||||
|
||||
|
||||
if gridStep > 0 and toolSettings.axis[3][2] then
|
||||
pos.z = helpers.roundToMultiple(newPos.z, gridStep)
|
||||
else
|
||||
pos.z = newPos.z
|
||||
end
|
||||
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
|
||||
|
||||
engine.input:mouseLeftReleased(function()
|
||||
leftButtonDown = false
|
||||
end)
|
||||
|
||||
updateHandles = function()
|
||||
if #selectionController.selection == 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
|
||||
local b = selectionController.selection[1]
|
||||
v[1].position = b.position + b.rotation* ((v[2] * b.size/2) + (v[2]*1.5))
|
||||
v[1]:lookAt(b.position)
|
||||
v[1].rotation = v[1].rotation * quaternion():setEuler(math.rad(-90),math.rad(90),0)
|
||||
v[1].size = vector3(0.35, 0.35, 0.35)
|
||||
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
|
||||
end
|
||||
|
||||
return toolsController:register({
|
||||
|
||||
name = TOOL_NAME,
|
||||
icon = TOOL_ICON,
|
||||
description = TOOL_DESCRIPTION,
|
||||
|
||||
hotKey = enums.key.number4,
|
||||
|
||||
activated = onToolActivated,
|
||||
deactivated = onToolDeactivated
|
||||
|
||||
})
|
|
@ -1,244 +0,0 @@
|
|||
--[[
|
||||
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
|
||||
|
||||
})
|
|
@ -1,141 +0,0 @@
|
|||
--[[
|
||||
Copyright 2019 Teverse
|
||||
@File paint.lua
|
||||
@Author(s) TheCakeChicken
|
||||
--]]
|
||||
|
||||
TOOL_NAME = "Paint"
|
||||
TOOL_ICON = "fa:s-paint-brush"
|
||||
TOOL_DESCRIPTION = "Use this to paint your blocks."
|
||||
|
||||
local toolsController = require("tevgit:create/controllers/tool.lua")
|
||||
local uiController = require("tevgit:create/controllers/ui.lua")
|
||||
local selectionController = require("tevgit:create/controllers/select.lua")
|
||||
|
||||
local toolActive = false
|
||||
local currentColour = colour:fromRGB(255,255,255)
|
||||
|
||||
local configWindow = uiController.createWindow(uiController.workshop.interface, guiCoord(0, 66, 0, 203), guiCoord(0, 140, 0, 90), "Colour Picker")
|
||||
|
||||
local colourDisplay = engine.construct("guiFrame", configWindow.content, {
|
||||
name = "colourPreview",
|
||||
position = guiCoord(1, -25, 0, 5),
|
||||
size = guiCoord(0, 20, 1, -10),
|
||||
backgroundColour = currentColour
|
||||
})
|
||||
|
||||
local redLabel = uiController.create("guiTextBox", configWindow.content, {
|
||||
size = guiCoord(0, 20, 0, 16),
|
||||
position = guiCoord(0, 5, 0, 5),
|
||||
multiline = false,
|
||||
fontSize = 16,
|
||||
text = "R",
|
||||
align = enums.align.middle
|
||||
}, "mainTopBar")
|
||||
|
||||
local greenLabel = uiController.create("guiTextBox", configWindow.content, {
|
||||
size = guiCoord(0, 20, 0, 16),
|
||||
position = guiCoord(0, 5, 0, 26),
|
||||
multiline = false,
|
||||
fontSize = 16,
|
||||
text = "G",
|
||||
align = enums.align.middle
|
||||
}, "mainTopBar")
|
||||
|
||||
local blueLabel = uiController.create("guiTextBox", configWindow.content, {
|
||||
size = guiCoord(0, 20, 0, 16),
|
||||
position = guiCoord(0, 5, 0, 47),
|
||||
multiline = false,
|
||||
fontSize = 16,
|
||||
text = "B",
|
||||
align = enums.align.middle
|
||||
}, "mainTopBar")
|
||||
|
||||
local redInput = uiController.create("guiTextBox", configWindow.content, {
|
||||
size = guiCoord(1, -60, 0, 16),
|
||||
position = guiCoord(0, 30, 0, 5),
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
text = "255",
|
||||
align = enums.align.middle,
|
||||
name = "redInput"
|
||||
}, "main")
|
||||
|
||||
local greenInput = uiController.create("guiTextBox", configWindow.content, {
|
||||
size = guiCoord(1, -60, 0, 16),
|
||||
position = guiCoord(0, 30, 0, 26),
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
text = "255",
|
||||
align = enums.align.middle,
|
||||
name = "greenInput"
|
||||
}, "main")
|
||||
|
||||
local blueInput = uiController.create("guiTextBox", configWindow.content, {
|
||||
size = guiCoord(1, -60, 0, 16),
|
||||
position = guiCoord(0, 30, 0, 47),
|
||||
readOnly = false,
|
||||
multiline = false,
|
||||
fontSize = 18,
|
||||
text = "255",
|
||||
align = enums.align.middle,
|
||||
name = "blueInput"
|
||||
}, "main")
|
||||
|
||||
configWindow.visible = false
|
||||
|
||||
local function updateColour()
|
||||
currentColour = colour:fromRGB(tonumber(redInput.text), tonumber(greenInput.text), tonumber(blueInput.text))
|
||||
colourDisplay.backgroundColour = currentColour
|
||||
end
|
||||
|
||||
redInput:textInput(updateColour)
|
||||
greenInput:textInput(updateColour)
|
||||
blueInput:textInput(updateColour)
|
||||
|
||||
local function paintAllSelected()
|
||||
if not toolActive then return end
|
||||
for _,object in next,selectionController.selection do
|
||||
object.colour = currentColour
|
||||
end
|
||||
end
|
||||
|
||||
local function onToolActivated(toolId)
|
||||
configWindow.visible = true
|
||||
toolActive = true
|
||||
|
||||
if selectionController.selection[1] then
|
||||
local obj = selectionController.selection[1]
|
||||
local r = obj.colour.r * 255
|
||||
local g = obj.colour.g * 255
|
||||
local b = obj.colour.b * 255
|
||||
|
||||
redInput.text = tostring(r)
|
||||
greenInput.text = tostring(g)
|
||||
blueInput.text = tostring(b)
|
||||
updateColour()
|
||||
end
|
||||
|
||||
selectionController.boundingBox:changed(paintAllSelected)
|
||||
paintAllSelected()
|
||||
end
|
||||
|
||||
local function onToolDeactivated(toolId)
|
||||
configWindow.visible = false
|
||||
toolActive = false
|
||||
end
|
||||
|
||||
return toolsController:register({
|
||||
|
||||
name = TOOL_NAME,
|
||||
icon = TOOL_ICON,
|
||||
description = TOOL_DESCRIPTION,
|
||||
|
||||
hotKey = enums.key.number6,
|
||||
|
||||
activated = onToolActivated,
|
||||
deactivated = onToolDeactivated
|
||||
|
||||
})
|
|
@ -1,279 +0,0 @@
|
|||
TOOL_NAME = "Resize"
|
||||
TOOL_ICON = "fa:s-expand-arrows-alt"
|
||||
TOOL_DESCRIPTION = "Use this to resize primitives."
|
||||
|
||||
|
||||
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 updateHandles
|
||||
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
|
||||
})
|
||||
|
||||
local originalSizes = {}
|
||||
|
||||
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
|
||||
|
||||
-- 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 thisI = i
|
||||
|
||||
local handle = engine.construct("block", nil, {
|
||||
name = "_CreateMode_",
|
||||
castsShadows = false,
|
||||
opacity = 0,
|
||||
doNotSerialise=true,
|
||||
renderQueue=1,
|
||||
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:sphere"
|
||||
})
|
||||
|
||||
handle:mouseLeftPressed(function()
|
||||
if leftButtonDown then return end -- how
|
||||
print("handle")
|
||||
updateHandles()
|
||||
leftButtonDown = handle
|
||||
|
||||
selectionController.selectable = false
|
||||
gridGuideline.size = vector3(300, 0.2, 300)
|
||||
gridGuideline.rotation = handle.rotation
|
||||
gridGuideline.opacity = 0
|
||||
gridGuideline.position = handle.position
|
||||
wait()
|
||||
|
||||
|
||||
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 = {}
|
||||
|
||||
|
||||
local lastHit = mouseHit.hitPosition
|
||||
|
||||
originalSizes = {}
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
mouseoffsets[v] = {(lastHit - v.position), v.position, v.size}
|
||||
originalSizes[v] = v.size
|
||||
end
|
||||
|
||||
-- For history and adding undo points.
|
||||
|
||||
|
||||
|
||||
local gridStep = toolSettings.gridStep
|
||||
|
||||
repeat
|
||||
if toolsController.currentToolId == toolId then
|
||||
--Face camera on one Axis
|
||||
--gridGuideline.position = handle.position
|
||||
--gridGuideline.rotation = handle.rotation
|
||||
|
||||
if component == "y" then
|
||||
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
|
||||
--print(target-lastHit)
|
||||
local moved = lastHit - target
|
||||
--lastHit = target
|
||||
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
if mouseoffsets[v] then
|
||||
local newPos = target - mouseoffsets[v][1]
|
||||
|
||||
|
||||
--print("moved 1", newPos - mouseoffsets[v][2])
|
||||
|
||||
local pos = mouseoffsets[v][2]:clone()
|
||||
|
||||
if component == "y" then
|
||||
if gridStep > 0 and toolSettings.axis[2][2] then
|
||||
pos.y = helpers.roundToMultiple(newPos.y, gridStep)
|
||||
else
|
||||
pos.y = newPos.y
|
||||
end
|
||||
else
|
||||
-- newPos = newPos - vector3(0.05, 0, 0.05)
|
||||
if gridStep > 0 and toolSettings.axis[1][2] then
|
||||
pos.x = helpers.roundToMultiple(newPos.x, gridStep)
|
||||
else
|
||||
pos.x = newPos.x
|
||||
end
|
||||
|
||||
|
||||
if gridStep > 0 and toolSettings.axis[3][2] then
|
||||
pos.z = helpers.roundToMultiple(newPos.z, gridStep)
|
||||
else
|
||||
pos.z = newPos.z
|
||||
end
|
||||
end
|
||||
|
||||
local totalMoved = pos - mouseoffsets[v][2]
|
||||
local totalMovedSize = totalMoved:clone() * 2
|
||||
|
||||
if component ~= "x" then
|
||||
totalMovedSize.x = 0
|
||||
end
|
||||
if component ~= "y" then
|
||||
totalMovedSize.y = 0
|
||||
end
|
||||
if component ~= "z" then
|
||||
totalMovedSize.z = 0
|
||||
end
|
||||
|
||||
--print("moved 2", totalMoved)
|
||||
if thisI % 2 == 0 then
|
||||
v.size = (mouseoffsets[v][3] + totalMovedSize):max(vector3(0.1, 0.1, 0.1))
|
||||
v.position = mouseoffsets[v][2] --+ (totalMoved/2)
|
||||
else
|
||||
v.size = (mouseoffsets[v][3] - totalMovedSize):max(vector3(0.1, 0.1, 0.1))
|
||||
v.position = mouseoffsets[v][2] --+ (totalMoved/2)
|
||||
end
|
||||
--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()
|
||||
--print("Event fired")
|
||||
leftButtonDown = false
|
||||
|
||||
if originalSizes then
|
||||
for item, size in pairs(originalSizes) do
|
||||
history.addPoint(item, "size", size)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
updateHandles = function()
|
||||
if #selectionController.selection == 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
|
||||
local b = selectionController.selection[1]
|
||||
v[1].position = b.position + b.rotation* ((v[2] * b.size/2) + (v[2]*1.5))
|
||||
v[1]:lookAt(b.position)
|
||||
v[1].rotation = v[1].rotation * quaternion():setEuler(math.rad(-90),math.rad(90),0)
|
||||
v[1].size = vector3(0.35, 0.35, 0.35)
|
||||
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.number4,
|
||||
|
||||
activated = onToolActivated,
|
||||
deactivated = onToolDeactivated
|
||||
|
||||
})
|
|
@ -1,234 +0,0 @@
|
|||
--[[
|
||||
Copyright 2019 Teverse
|
||||
@File rotate.lua
|
||||
@Author(s) Jay
|
||||
--]]
|
||||
|
||||
TOOL_NAME = "Rotate"
|
||||
TOOL_ICON = "fa:s-sync-alt"
|
||||
TOOL_DESCRIPTION = "Use this to rotate objects"
|
||||
|
||||
local sensitivity = 50
|
||||
|
||||
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 arrows = {
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
}
|
||||
|
||||
-- Each axis gets four arrows...
|
||||
-- This table maps each arrow index to an vertice index
|
||||
local arrowsVerticesMap = {
|
||||
{6, 4, 2, 1}, --x
|
||||
{2, 1, 7, 6}, --y
|
||||
{5, 7, 3, 1} --z
|
||||
}
|
||||
|
||||
local function positionArrows()
|
||||
if selectionController.boundingBox.size == vector3(0,0,0) then
|
||||
for _,v in pairs(arrows) do
|
||||
for i,arrow in pairs(v) do
|
||||
arrow.physics = false
|
||||
arrow.opacity = 0
|
||||
end
|
||||
end
|
||||
else
|
||||
local vertices = helpers.calculateVertices(selectionController.boundingBox)
|
||||
|
||||
for a,v in pairs(arrows) do
|
||||
for i,arrow in pairs(v) do
|
||||
if i == 2 then i = 3 end
|
||||
arrow.physics = true
|
||||
arrow.opacity = 1
|
||||
arrow.position = vertices[arrowsVerticesMap[a][i]]
|
||||
if a == 1 then
|
||||
arrow.rotation = quaternion:setEuler(math.rad((i)*90), 0, math.rad(-90))
|
||||
elseif a == 2 then
|
||||
arrow.rotation = quaternion:setEuler(0, math.rad((i-1)*-90), 0)
|
||||
else
|
||||
arrow.rotation = quaternion:setEuler(math.rad((i-1)*-90), math.rad(90), math.rad(90))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local boundingEvent
|
||||
|
||||
-- calculates angle ABC
|
||||
-- returns in radians
|
||||
local function calculateAngleBetween3Points(a, b, c)
|
||||
local v1 = a - b
|
||||
local v2 = c - b
|
||||
return math.acos(v1:normal():dot(v2:normal()))
|
||||
end
|
||||
|
||||
local function calculateCircleAngle(hitbox, pos)
|
||||
local hitboxPosition = hitbox.position
|
||||
local hitboxRotation = hitbox.rotation
|
||||
|
||||
local hitboxUp = hitboxPosition + (hitboxRotation * vector3(0,0,-10))
|
||||
local hitboxRight = hitboxPosition + (hitboxRotation * vector3(10,0,0))
|
||||
|
||||
local angle = calculateAngleBetween3Points(hitboxUp, hitboxPosition, pos)
|
||||
if hitboxRight:dot(pos) < 0 then
|
||||
angle = (math.pi-angle)+math.pi
|
||||
end
|
||||
|
||||
return angle
|
||||
end
|
||||
|
||||
local function onToolActivated(toolId)
|
||||
for axis = 1, 3 do
|
||||
local newArrow = engine.construct("block", engine.workspace, {
|
||||
name = "_CreateMode_",
|
||||
castsShadows = false,
|
||||
opacity = 0,
|
||||
renderQueue=1,
|
||||
doNotSerialise=true,
|
||||
size = vector3(.4, 0.1, .4),
|
||||
colour = colour(axis == 1 and 1 or 0, axis == 2 and 1 or 0, axis == 3 and 1 or 0),
|
||||
emissiveColour = colour(axis == 1 and 0.5 or 0, axis == 2 and 0.5 or 0, axis == 3 and 0.5 or 0),
|
||||
workshopLocked = true,
|
||||
mesh = "tevurl:3d/arrowCurved.glb"
|
||||
})
|
||||
|
||||
newArrow:mouseLeftPressed(function ()
|
||||
local hitbox = engine.construct("block", workspace, {
|
||||
name = "_CreateMode_",
|
||||
castsShadows = false,
|
||||
opacity = 0,
|
||||
renderQueue = 1,
|
||||
doNotSerialise=true,
|
||||
size = vector3(60, 0.1, 60),
|
||||
workshopLocked = true,
|
||||
position = helpers.getCentreOfFace(selectionController.boundingBox, (axis*2)-1),
|
||||
rotation = newArrow.rotation
|
||||
})
|
||||
hitbox.rotation = hitbox.rotation:setLookRotation( hitbox.position - workspace.camera.position ) * quaternion():setEuler(math.rad(90),0,0)
|
||||
--hitbox:lookAt(workspace.camera.position)
|
||||
|
||||
local mouseHits = engine.physics:rayTestScreenAllHits( engine.input.mousePosition )
|
||||
local mouseHit = nil
|
||||
for _,hit in pairs(mouseHits) do
|
||||
if hit.object == hitbox then
|
||||
mouseHit = hit
|
||||
goto skip_loop
|
||||
end
|
||||
end
|
||||
::skip_loop::
|
||||
|
||||
if not mouseHit then
|
||||
print("Did not collide")
|
||||
hitbox:destroy()
|
||||
return nil
|
||||
end
|
||||
|
||||
local startRotations = {}
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
startRotations[v] = v.rotation
|
||||
print("Start, ", v)
|
||||
end
|
||||
|
||||
local start = mouseHit.hitPosition
|
||||
|
||||
while engine.input:isMouseButtonDown(enums.mouseButton.left) and wait() do
|
||||
|
||||
hitbox.rotation = hitbox.rotation:setLookRotation( hitbox.position - workspace.camera.position ) * quaternion():setEuler(math.rad(90),0,0)
|
||||
|
||||
local mouseHits = engine.physics:rayTestScreenAllHits( engine.input.mousePosition )
|
||||
local mouseHit = nil
|
||||
for _,hit in pairs(mouseHits) do
|
||||
if hit.object == hitbox then
|
||||
mouseHit = hit
|
||||
goto skip_loop
|
||||
end
|
||||
end
|
||||
::skip_loop::
|
||||
|
||||
if mouseHit then
|
||||
local current = mouseHit.hitPosition
|
||||
local diff = (start-current)
|
||||
local travelled = diff:length()
|
||||
|
||||
-- length of vectors is never less than 0. let's fix that
|
||||
if (newArrow.rotation * vector3(0,0,1)):dot(diff) < 0 then
|
||||
--user moved their mouse in an opposite direction to the arrow
|
||||
travelled = -travelled
|
||||
end
|
||||
|
||||
local n = helpers.roundToMultiple(math.rad(travelled*sensitivity), toolSettings.rotateStep)
|
||||
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
if startRotations[v] then
|
||||
local euler = vector3(
|
||||
axis == 1 and n or 0,
|
||||
axis == 2 and n or 0,
|
||||
axis == 3 and n or 0
|
||||
)
|
||||
|
||||
v.rotation = v.rotation * quaternion:setEuler(v.rotation:inverse() * euler)
|
||||
end
|
||||
end
|
||||
|
||||
if n ~= 0 then
|
||||
start = current
|
||||
end
|
||||
end
|
||||
end
|
||||
hitbox:destroy()
|
||||
|
||||
for _,v in pairs(selectionController.selection) do
|
||||
print("END", v)
|
||||
if startRotations[v] and startRotations[v] ~= v.rotation then
|
||||
history.addPoint(v, "rotation", startRotations[v])
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
|
||||
|
||||
table.insert(arrows[axis], newArrow)
|
||||
end
|
||||
|
||||
boundingEvent = selectionController.boundingBox:changed(positionArrows)
|
||||
|
||||
positionArrows()
|
||||
end
|
||||
|
||||
local function onToolDeactivated(toolId)
|
||||
boundingEvent:disconnect()
|
||||
boundingEvent = nil
|
||||
|
||||
for _,v in pairs(arrows) do
|
||||
for _,arrow in pairs(v) do
|
||||
print(arrow)
|
||||
arrow:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
arrows = {
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
}
|
||||
end
|
||||
|
||||
return toolsController:register({
|
||||
name = TOOL_NAME,
|
||||
icon = TOOL_ICON,
|
||||
description = TOOL_DESCRIPTION,
|
||||
|
||||
hotKey = enums.key.number5,
|
||||
|
||||
activated = onToolActivated,
|
||||
deactivated = onToolDeactivated
|
||||
})
|
|
@ -1,163 +0,0 @@
|
|||
--[[
|
||||
Copyright 2019 Teverse
|
||||
@File select.lua
|
||||
@Author(s) Jay, joritochip
|
||||
--]]
|
||||
|
||||
-- TODO: Create a UI that allows the user to input a step size
|
||||
print("load")
|
||||
TOOL_NAME = "Select"
|
||||
TOOL_ICON = "fa:s-hand-paper"
|
||||
TOOL_DESCRIPTION = "Use this select and move primitives."
|
||||
|
||||
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 function onToolActivated(toolId)
|
||||
local mouseDown = 0
|
||||
local applyRot = 0
|
||||
local gridStep = toolSettings.gridStep
|
||||
|
||||
selectionController.selectable = true
|
||||
|
||||
toolsController.tools[toolId].data.mouseDownEvent = engine.input:mouseLeftPressed(function ( inp )
|
||||
if not inp.systemHandled and #selectionController.selection > 0 then
|
||||
|
||||
applyRot = 0
|
||||
|
||||
local selectionAtBegin = selectionController.selection
|
||||
|
||||
local hit, didExclude = engine.physics:rayTestScreenAllHits(engine.input.mousePosition,
|
||||
selectionAtBegin)
|
||||
|
||||
local objectSelectedHit = nil
|
||||
local objectSelectedHits = engine.physics:rayTestScreenAllHits(engine.input.mousePosition)
|
||||
for _,v in pairs(objectSelectedHits) do
|
||||
for _,vv in pairs(selectionAtBegin) do
|
||||
if vv == v.object then
|
||||
objectSelectedHit = v
|
||||
goto continue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
::continue::
|
||||
|
||||
-- Didexclude is false if the user didnt drag starting from one of the selected items.
|
||||
if didExclude == false or not objectSelectedHit then return end
|
||||
|
||||
|
||||
local currentTime = os.clock()
|
||||
mouseDown = currentTime
|
||||
|
||||
wait(0.25)
|
||||
if mouseDown == currentTime then
|
||||
--user held mouse down for 0.25 seconds,
|
||||
--initiate drag
|
||||
|
||||
selectionController.selectable = false
|
||||
|
||||
hit = hit and hit[1] or nil
|
||||
local startPosition = hit and hit.hitPosition or vector3(0,0,0)
|
||||
local startOffset = (objectSelectedHit.object.position -objectSelectedHit.hitPosition)
|
||||
startOffset.y =0
|
||||
local lastPosition = startPosition
|
||||
local startRotation = objectSelectedHit.object.rotation
|
||||
local offsets = {}
|
||||
|
||||
for i,v in pairs(selectionAtBegin) do
|
||||
if v ~= objectSelectedHit.object then
|
||||
local relative = startRotation:inverse() * v.rotation;
|
||||
local positionOffset = (relative*objectSelectedHit.object.rotation):inverse() * (v.position - objectSelectedHit.object.position)
|
||||
offsets[v] = {positionOffset, relative}
|
||||
end
|
||||
end
|
||||
|
||||
local lastRot = applyRot
|
||||
|
||||
while mouseDown == currentTime and toolsController.currentToolId == toolId do
|
||||
local currentHit = engine.physics:rayTestScreenAllHits(engine.input.mousePosition, selectionAtBegin)
|
||||
if #currentHit >= 1 then
|
||||
currentHit = currentHit[1]
|
||||
|
||||
-- supposed to get the face of the object the mouse it over, and then position the block to be on that face.
|
||||
local forward = (currentHit.object.rotation * currentHit.hitNormal):normal()-- * quaternion:setEuler(0,math.rad(applyRot),0)
|
||||
|
||||
|
||||
local currentPosition = (currentHit.hitPosition) + startOffset + (forward * (objectSelectedHit.object.size/2)) --+ (selectedItems[1].size/2)
|
||||
|
||||
currentPosition = helpers.roundVectorWithToolSettings(currentPosition)
|
||||
|
||||
if lastPosition ~= currentPosition or lastRot ~= applyRot then
|
||||
lastRot = applyRot
|
||||
lastPosition = currentPosition
|
||||
|
||||
local targetRot = startRotation * quaternion:setEuler(0,math.rad(applyRot),0)
|
||||
|
||||
--engine.tween:begin(selectionAtBegin[1], .2, {position = currentPosition,
|
||||
-- rotation = targetRot }, "outQuad")
|
||||
|
||||
objectSelectedHit.object.position = currentPosition
|
||||
objectSelectedHit.object.rotation = targetRot
|
||||
|
||||
for i,v in pairs(selectionAtBegin) do
|
||||
if v ~= objectSelectedHit.object then
|
||||
v.position = (currentPosition) + (offsets[v][2]*targetRot) * offsets[v][1]
|
||||
v.rotation = offsets[v][2]*targetRot
|
||||
|
||||
--engine.tween:begin(v, .2, {position = (currentPosition) + (offsets[v][2]*targetRot) * offsets[v][1],
|
||||
-- rotation = offsets[v][2]*targetRot }, "outQuad")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
--calculateBoundingBox()
|
||||
wait()
|
||||
end
|
||||
selectionController.selectable = true
|
||||
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
toolsController.tools[toolId].data.mouseUpEvent = engine.input:mouseLeftReleased(function ( inp )
|
||||
mouseDown = 0
|
||||
end)
|
||||
|
||||
toolsController.tools[toolId].data.keyPressedEvent = engine.input:keyPressed(function(input)
|
||||
if input.systemHandled then return end
|
||||
|
||||
if input.key == enums.key.r then
|
||||
applyRot = applyRot + 45
|
||||
--gridStep = gridStep == 1 and 0 or 1
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function onToolDeactivated(toolId)
|
||||
--clean up
|
||||
toolsController.tools[toolId].data.mouseDownEvent:disconnect()
|
||||
toolsController.tools[toolId].data.mouseDownEvent = nil
|
||||
toolsController.tools[toolId].data.mouseUpEvent:disconnect()
|
||||
toolsController.tools[toolId].data.mouseUpEvent = nil
|
||||
toolsController.tools[toolId].data.keyPressedEvent:disconnect()
|
||||
toolsController.tools[toolId].data.keyPressedEvent = nil
|
||||
end
|
||||
|
||||
return toolsController:register({
|
||||
|
||||
name = TOOL_NAME,
|
||||
icon = TOOL_ICON,
|
||||
description = TOOL_DESCRIPTION,
|
||||
|
||||
hotKey = enums.key.number2,
|
||||
|
||||
activated = onToolActivated,
|
||||
deactivated = onToolDeactivated,
|
||||
|
||||
data = {axis={{"x", true},{"y", false},{"z", true}}}
|
||||
|
||||
})
|
|
@ -38,7 +38,7 @@ local function runTutorial(module)
|
|||
position = guiCoord(0,10,0,0),
|
||||
backgroundAlpha = 0,
|
||||
align = enums.align.middleLeft,
|
||||
fontFile = "OpenSans-SemiBold.ttf",
|
||||
fontFile = "local:OpenSans-SemiBold.ttf",
|
||||
fontSize = 24,
|
||||
text = tutorial.name
|
||||
})
|
||||
|
@ -48,7 +48,7 @@ local function runTutorial(module)
|
|||
position = guiCoord(0,(title.textDimensions.x + 20),0,0),
|
||||
backgroundAlpha = 0,
|
||||
align = enums.align.middleLeft,
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
fontFile = "local:OpenSans-Regular.ttf",
|
||||
fontSize = 18,
|
||||
textAlpha = 0.5,
|
||||
text = tutorial.description
|
||||
|
@ -93,7 +93,7 @@ local function runTutorial(module)
|
|||
backgroundAlpha = 0,
|
||||
align = enums.align.topLeft,
|
||||
wrap = true,
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
fontFile = "local:OpenSans-Regular.ttf",
|
||||
fontSize = 20,
|
||||
text = page,
|
||||
textColour = colour:black(),
|
||||
|
@ -105,7 +105,7 @@ local function runTutorial(module)
|
|||
size = guiCoord(0, 120, 0, 24),
|
||||
position = guiCoord(0,5,0,txt.textDimensions.y + 15),
|
||||
align = enums.align.middle,
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
fontFile = "local:OpenSans-Regular.ttf",
|
||||
fontSize = 20,
|
||||
text = "Next",
|
||||
backgroundColour= colour(0.4, 0.4, 0.4),
|
||||
|
@ -129,7 +129,7 @@ local function runTutorial(module)
|
|||
backgroundAlpha = 0,
|
||||
align = enums.align.topLeft,
|
||||
wrap = true,
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
fontFile = "local:OpenSans-Regular.ttf",
|
||||
fontSize = 20,
|
||||
text = v,
|
||||
textColour = colour:black(),
|
||||
|
@ -143,7 +143,7 @@ local function runTutorial(module)
|
|||
size = guiCoord(0, 120, 0, 22),
|
||||
position = guiCoord(0,5,0,y),
|
||||
align = enums.align.middle,
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
fontFile = "local:OpenSans-Regular.ttf",
|
||||
fontSize = 20,
|
||||
text = "Continue",
|
||||
backgroundColour= colour(0.4, 0.4, 0.4),
|
||||
|
@ -165,7 +165,7 @@ local function runTutorial(module)
|
|||
size = guiCoord(0, 120, 0, 22),
|
||||
position = guiCoord(0,5,0,y),
|
||||
align = enums.align.middle,
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
fontFile = "local:OpenSans-Regular.ttf",
|
||||
fontSize = 20,
|
||||
text = v.btnText,
|
||||
backgroundColour= colour(0.4, 0.4, 0.4),
|
||||
|
@ -215,7 +215,7 @@ local function createMainInterface()
|
|||
position = guiCoord(0,10,0,10),
|
||||
backgroundAlpha = 0,
|
||||
align = enums.align.middleLeft,
|
||||
fontFile = "OpenSans-SemiBold.ttf",
|
||||
fontFile = "local:OpenSans-SemiBold.ttf",
|
||||
fontSize = 24,
|
||||
text = section
|
||||
})
|
||||
|
@ -249,7 +249,7 @@ local function createMainInterface()
|
|||
backgroundAlpha = 0.1,
|
||||
textAlpha = 0.5,
|
||||
align = enums.align.middle,
|
||||
fontFile = "OpenSans-SemiBold.ttf",
|
||||
fontFile = "local:OpenSans-SemiBold.ttf",
|
||||
fontSize = 20,
|
||||
backgroundColour= colour:black(),
|
||||
text = tostring(i),
|
||||
|
@ -261,7 +261,7 @@ local function createMainInterface()
|
|||
position = guiCoord(0,40,0,5),
|
||||
backgroundAlpha = 0,
|
||||
align = enums.align.middleLeft,
|
||||
fontFile = "OpenSans-Regular.ttf",
|
||||
fontFile = "local:OpenSans-Regular.ttf",
|
||||
fontSize = 20,
|
||||
text = tutorial[1],
|
||||
handleEvents = false,
|
||||
|
|
1641
workshop.lua
1641
workshop.lua
File diff suppressed because it is too large
Load Diff
|
@ -64,18 +64,18 @@ local function updatePositions(frame)
|
|||
frame.icon.texture = regularIconWithChildren
|
||||
frame.icon.imageAlpha = 1
|
||||
frame.textAlpha = 1
|
||||
frame.fontFile = "OpenSans-SemiBold.ttf"
|
||||
frame.fontFile = "local:OpenSans-SemiBold.ttf"
|
||||
else
|
||||
-- object has no children
|
||||
frame.icon.texture = regularIconWithOutChildren
|
||||
frame.icon.imageAlpha = .2
|
||||
frame.textAlpha = .6
|
||||
frame.fontFile = "OpenSans-Regular.ttf"
|
||||
frame.fontFile = "local:OpenSans-Regular.ttf"
|
||||
end
|
||||
else
|
||||
-- object is expanded
|
||||
frame.textAlpha = 0.6
|
||||
frame.fontFile = "OpenSans-Regular.ttf"
|
||||
frame.fontFile = "local:OpenSans-Regular.ttf"
|
||||
frame.icon.imageAlpha = 0.4
|
||||
frame.icon.texture = expandedIcon
|
||||
end
|
||||
|
@ -137,8 +137,8 @@ local function createHierarchyButton(object, guiParent)
|
|||
end
|
||||
controller.scrollView.canvasSize =
|
||||
guiCoord(1, 0, 0, updatePositions())
|
||||
if object.className == "scriptSource" or object.className ==
|
||||
"scriptContainer" then
|
||||
if object.className == "script" then
|
||||
object:editExternal()
|
||||
-- require("tevgit:create/controllers/scriptController.lua").editScript(object)
|
||||
end
|
||||
else
|
||||
|
@ -190,7 +190,9 @@ local function createHierarchyButton(object, guiParent)
|
|||
|
||||
if object:isA("luaSharedFolder") or object:isA("luaServerFolder") or
|
||||
object:isA("luaClientFolder") then
|
||||
context.bind(btn, context.exampleOptions)
|
||||
context.bind(btn, {
|
||||
{name = "Add Script", callback = function() engine.construct("script", object) end}
|
||||
})
|
||||
else
|
||||
-- selectionController.applyContext(btn)
|
||||
end
|
||||
|
|
|
@ -64,9 +64,9 @@ controller.generateMenu = function(options, position)
|
|||
textAlpha = 0.6
|
||||
}, "primaryText")
|
||||
|
||||
if options.callback then
|
||||
if option.callback then
|
||||
btn:mouseLeftReleased(function ()
|
||||
options.callback()
|
||||
option.callback()
|
||||
menu:destroy()
|
||||
controller.currentContextMenu = nil
|
||||
end)
|
||||
|
|
|
@ -205,7 +205,7 @@ return {
|
|||
zIndex = 2,
|
||||
text = "Continue",
|
||||
align = enums.align.middle,
|
||||
fontFile = "OpenSans-Bold.ttf"
|
||||
fontFile = "local:OpenSans-Bold.ttf"
|
||||
}, themer.types.primaryVariant)
|
||||
|
||||
if not callback then
|
||||
|
|
Loading…
Reference in New Issue