mirror of https://github.com/teverse/teverse
Compare commits
92 Commits
81a3ca294c
...
68cff74b1f
Author | SHA1 | Date |
---|---|---|
Sanjay Bhadra | 68cff74b1f | |
Jay | f4e0ae6139 | |
Jay | 6876f15b5c | |
Jay | 498cb68083 | |
Josh Muir | 85dd40e95a | |
Josh Muir | 5d0584f3cb | |
Josh Muir | f3129a77a5 | |
Sanjay | 3a6b2565f6 | |
Jay | 3971aed6a3 | |
Jay | 6efd379391 | |
Jay | cf3929e790 | |
Sanjay | 8ee1e633e2 | |
Sanjay Bhadra | dc2577fb8b | |
Sanjay Bhadra | 547fa8d97b | |
Sanjay Bhadra | 59e8f168ff | |
Sanjay | a09916531e | |
Jay | 9cc085edf3 | |
Jay | 8c7e69560d | |
Jay | 90695eee40 | |
Jay | 858aac9274 | |
Jay | 6840ac51c1 | |
Sanjay Bhadra | 5a829404fc | |
Jay | a554a87f84 | |
Jay | 9f5ad0ee7f | |
Sanjay | 55a1ca4454 | |
Jay | 44c6d455dc | |
Jay | 1a340567a5 | |
Jay | f170c4eac2 | |
teverse | 6d3fcbc08a | |
teverse | 2da7b377ef | |
Sanjay Bhadra | ac8feee10f | |
Jay | fa2a04db52 | |
Jay | bad6904690 | |
Jay | 690b947726 | |
Sanjay Bhadra | 3e3db80ebb | |
Jay | 6a2ed2629f | |
Jay | 17599a6eaf | |
Jay | cb36ce065a | |
Jay | 9f22dbeda8 | |
Jay | fed726139e | |
Jay | a4d81aa668 | |
Jay | 39fecf6e54 | |
Jay | f5346a4383 | |
Sanjay Bhadra | 77038455d1 | |
Jay | b30fbca745 | |
Jay | 448fb6e37b | |
Jay | 4c83652c30 | |
Jay | 1abb33e965 | |
Jay | 7c30939d24 | |
Sanjay Bhadra | 51676c685b | |
Sanjay Bhadra | 243e654a3f | |
Jay | 7174736ea9 | |
Sanjay Bhadra | 0c0322b855 | |
Sanjay Bhadra | da410f9eef | |
Jay | d859b4b0e1 | |
Jay | 14a0f6d3ae | |
Jay | 3d714a1450 | |
Jay | 378dc7af60 | |
Jay | 7bd1212552 | |
Jay | ca077e22b2 | |
Jay | 155e2ac581 | |
Jay | 3c2e30b424 | |
Jay | 74012b5fa8 | |
Jay | eaf899db28 | |
Jay | 2e92d94a9f | |
Jay | c6e33b743d | |
Sanjay | 2e0fa7a913 | |
Jay | 1e4e1af8a9 | |
Jay | 740580e6a1 | |
Jay | 262651e631 | |
Jay | f2bd275687 | |
Jay | 16266ee0b9 | |
Jay | 267f97d5d6 | |
Jay | eb69b31e34 | |
Jay | a2fbd3032d | |
Jay | 23c9c1cdb6 | |
Jay | a9b9d0dec6 | |
Jay | a016fe1676 | |
Jay | b39b953fa6 | |
Jay | 4b479a483e | |
Jay | 1434cef53f | |
Jay | a0fb4dcfb7 | |
Jay | 61e3a7347a | |
Jay | b676abadef | |
Jay | 036bbb8ee2 | |
Sanjay Bhadra | c4f3c75900 | |
Sanjay Bhadra | e042e4b71b | |
Sanjay Bhadra | 7b49c94906 | |
Sanjay Bhadra | 1cf50c3fc2 | |
Sanjay Bhadra | 02a0068bd5 | |
teverse | 519fa3ee76 | |
Sanjay Bhadra | 4d7d284a02 |
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
This repo contains open source components produced for Teverse.
|
This repo contains open source components produced for Teverse.
|
||||||
|
|
||||||
Contains the redesigned components of Workshop (``./workshop``).
|
Contains the redesigned components of the dashboard, tutorials and Workshop (``./workshop``).
|
||||||
|
|
||||||
|
|
||||||
# Contributing to Teverse
|
# Contributing to Teverse
|
||||||
|
@ -22,4 +22,4 @@ Copyright (c) 2020 teverse.com
|
||||||
|
|
||||||
# Acknowledgements
|
# Acknowledgements
|
||||||
- sound/click.ogg sourced from http://soundbible.com/1705-Click2.html
|
- sound/click.ogg sourced from http://soundbible.com/1705-Click2.html
|
||||||
- sound/tick.ogg sourced from http://soundbible.com/2044-Tick.html
|
- sound/tick.ogg sourced from http://soundbible.com/2044-Tick.html
|
||||||
|
|
2500
apiDump.json
2500
apiDump.json
File diff suppressed because it is too large
Load Diff
|
@ -97,7 +97,7 @@ share:on("mouseLeftUp", function()
|
||||||
if code == 200 then
|
if code == 200 then
|
||||||
msg.text = "Your app was updated! Please note apps may be subject to moderation before becoming public."
|
msg.text = "Your app was updated! Please note apps may be subject to moderation before becoming public."
|
||||||
else
|
else
|
||||||
msg.text = "Something went wrong."
|
msg.text = "Something went wrong: "..code..body
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
-- This script is ran when the user is running a shared app
|
-- This script is ran when the user is running a shared app
|
||||||
|
|
||||||
local appsContainer = teverse.construct("guiTextBox", {
|
local disclaimer = teverse.construct("guiTextBox", {
|
||||||
parent = teverse.coreInterface,
|
parent = teverse.coreInterface,
|
||||||
size = guiCoord(1, 0, 0, 15),
|
size = guiCoord(0, 75, 0, 18),
|
||||||
position = guiCoord(0, 0, 1, -15),
|
position = guiCoord(0, 10, 1, -28),
|
||||||
backgroundAlpha = 0,
|
text = "User Content",
|
||||||
text = "You are running user generated code",
|
textSize = 14,
|
||||||
textShadowSize = 4,
|
textColour = colour(0, 0, 0),
|
||||||
textSize = 12,
|
textAlign = "middle",
|
||||||
textColour = colour(1, 1, 1),
|
textFont = "tevurl:fonts/openSansSemiBold.ttf",
|
||||||
textAlign = "middle"
|
strokeRadius = 2,
|
||||||
})
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
|
})
|
||||||
|
|
||||||
|
disclaimer:on("mouseLeftUp", function()
|
||||||
|
teverse.apps:reload()
|
||||||
|
end)
|
|
@ -1,3 +1,38 @@
|
||||||
|
local function createApp(app)
|
||||||
|
local appGui = teverse.construct("guiFrame", {
|
||||||
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.guiHelper.hoverColour(appGui, colour.rgb(247, 247, 247))
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = appGui,
|
||||||
|
size = guiCoord(1.0, -20, 0, 22),
|
||||||
|
position = guiCoord(0, 10, 0, 5),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = app.name,
|
||||||
|
textSize = 22,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
active = false
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = appGui,
|
||||||
|
size = guiCoord(1.0, -20, 0, 16),
|
||||||
|
position = guiCoord(0, 10, 0, 24),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
textAlpha = 0.5,
|
||||||
|
text = "by " .. app.owner.username,
|
||||||
|
textSize = 16,
|
||||||
|
active = false
|
||||||
|
})
|
||||||
|
|
||||||
|
return appGui
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name = "Apps",
|
name = "Apps",
|
||||||
iconId = "shapes",
|
iconId = "shapes",
|
||||||
|
@ -29,40 +64,61 @@ return {
|
||||||
local subtitle = teverse.construct("guiTextBox", {
|
local subtitle = teverse.construct("guiTextBox", {
|
||||||
parent = page,
|
parent = page,
|
||||||
size = guiCoord(1.0, -20, 0, 18),
|
size = guiCoord(1.0, -20, 0, 18),
|
||||||
position = guiCoord(0, 10, 0, 58),
|
position = guiCoord(0, 10, 0, 105),
|
||||||
backgroundAlpha = 0,
|
backgroundAlpha = 0,
|
||||||
text = "Loading Apps",
|
text = "Loading Apps",
|
||||||
textSize = 18,
|
textSize = 18,
|
||||||
textAlign = "middleLeft"
|
textAlign = "middleLeft"
|
||||||
})
|
})
|
||||||
|
|
||||||
local appsContainer = teverse.construct("guiFrame", {
|
local myApps = teverse.construct("guiFrame", {
|
||||||
parent = page,
|
parent = page,
|
||||||
size = guiCoord(1.0, -20, 1, -100),
|
size = guiCoord(1.0, -20, 0, 38),
|
||||||
position = guiCoord(0, 10, 0, 90),
|
position = guiCoord(0, 10, 0, 62),
|
||||||
backgroundAlpha = 0
|
backgroundAlpha = 0
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.http:get("https://teverse.com/api/users/" .. teverse.networking.localClient.id .. "/apps", {
|
||||||
.gridConstraint(appsContainer, {
|
|
||||||
cellSize = guiCoord(0, 150, 0, 80),
|
|
||||||
cellMargin = guiCoord(0, 15, 0, 25)
|
|
||||||
})
|
|
||||||
|
|
||||||
teverse.http:get("https://teverse.com/api/apps", {
|
|
||||||
["Authorization"] = "BEARER " .. teverse.userToken
|
["Authorization"] = "BEARER " .. teverse.userToken
|
||||||
}, function(code, body)
|
}, function(code, body)
|
||||||
if code == 200 then
|
if code == 200 then
|
||||||
local apps = teverse.json:decode(body)
|
local apps = teverse.json:decode(body)
|
||||||
subtitle.text = "Found " .. #apps .. " public apps."
|
for i,app in pairs(apps) do
|
||||||
for _,app in pairs(apps) do
|
|
||||||
local appGui = teverse.construct("guiFrame", {
|
local appGui = teverse.construct("guiFrame", {
|
||||||
parent = appsContainer,
|
strokeRadius = 2,
|
||||||
strokeAlpha = 0.1,
|
dropShadowAlpha = 0.15,
|
||||||
strokeRadius = 4
|
strokeAlpha = 0.05,
|
||||||
|
parent = myApps,
|
||||||
|
position = guiCoord(0, (i-1)*140, 0, 0),
|
||||||
|
size = guiCoord(0, 130, 1, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.guiHelper.hoverColour(appGui, colour.rgb(247, 247, 247))
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = appGui,
|
||||||
|
size = guiCoord(1.0, -20, 0, 16),
|
||||||
|
position = guiCoord(0, 10, 0, 5),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = app.name,
|
||||||
|
textSize = 18,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textFont = "tevurl:fonts/openSansSemiBold.ttf",
|
||||||
|
active = false
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = appGui,
|
||||||
|
size = guiCoord(1.0, -20, 0, 14),
|
||||||
|
position = guiCoord(0, 10, 0, 21),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = app.approved and "Approved" or "Pending",
|
||||||
|
textSize = 14,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
active = false
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper.hoverColour(appGui, colour.rgb(247, 247, 247))
|
|
||||||
appGui:on("mouseLeftUp", function()
|
appGui:on("mouseLeftUp", function()
|
||||||
if not loading.visible then
|
if not loading.visible then
|
||||||
loading.text = "Working..."
|
loading.text = "Working..."
|
||||||
|
@ -81,43 +137,76 @@ return {
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
teverse.construct("guiTextBox", {
|
local appsContainer = teverse.construct("guiFrame", {
|
||||||
parent = appGui,
|
parent = page,
|
||||||
size = guiCoord(1.0, -20, 0, 22),
|
size = guiCoord(1.0, -20, 1, -140),
|
||||||
position = guiCoord(0, 10, 0, 5),
|
position = guiCoord(0, 10, 0, 130),
|
||||||
backgroundAlpha = 0,
|
backgroundAlpha = 0
|
||||||
text = app.name,
|
})
|
||||||
textSize = 22,
|
|
||||||
textAlign = "middleLeft",
|
|
||||||
textFont = "tevurl:fonts/openSansBold.ttf",
|
|
||||||
active = false
|
|
||||||
})
|
|
||||||
|
|
||||||
teverse.construct("guiTextBox", {
|
if _DEVICE:sub(0, 6) == "iPhone" then
|
||||||
parent = appGui,
|
teverse.guiHelper
|
||||||
size = guiCoord(1.0, -20, 0, 16),
|
.gridConstraint(appsContainer, {
|
||||||
position = guiCoord(0, 10, 0, 24),
|
cellSize = guiCoord(0, page.absoluteSize.x - 20, 0, 50),
|
||||||
backgroundAlpha = 0,
|
cellMargin = guiCoord(0, 15, 0, 25)
|
||||||
textAlpha = 0.5,
|
})
|
||||||
text = "by " .. app.owner.username,
|
else
|
||||||
textSize = 16,
|
teverse.guiHelper
|
||||||
active = false
|
.gridConstraint(appsContainer, {
|
||||||
})
|
cellSize = guiCoord(0, 160, 0, 50),
|
||||||
|
cellMargin = guiCoord(0, 15, 0, 25)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
teverse.construct("guiIcon", {
|
if _DEVICE:sub(0, 6) ~= "iPhone" then
|
||||||
parent = appGui,
|
local appGui = createApp({
|
||||||
size = guiCoord(1, 0, 1, -45),
|
id = "",
|
||||||
position = guiCoord(0, 0, 0, 45),
|
name = "Learn Code",
|
||||||
iconMax = 20,
|
owner = {
|
||||||
iconColour = colour(1, 1, 1),
|
username = "Teverse"
|
||||||
iconType = "faSolid",
|
}
|
||||||
iconId = "code",
|
})
|
||||||
iconAlpha = 0.9,
|
appGui.name = "a"
|
||||||
backgroundAlpha = 1.0,
|
appGui.parent = appsContainer
|
||||||
backgroundColour = colour.rgb(216, 100, 89),
|
appGui:on("mouseLeftUp", function()
|
||||||
active = false
|
if not loading.visible then
|
||||||
})
|
loading.visible = false
|
||||||
|
teverse.apps:loadString("require('tevgit:core/tutorials/main.lua')")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
teverse.http:get("https://teverse.com/api/apps", {
|
||||||
|
["Authorization"] = "BEARER " .. teverse.userToken
|
||||||
|
}, function(code, body)
|
||||||
|
if code == 200 then
|
||||||
|
local apps = teverse.json:decode(body)
|
||||||
|
subtitle.text = "Found " .. #apps .. " public apps:"
|
||||||
|
for _,app in pairs(apps) do
|
||||||
|
local appGui = createApp(app)
|
||||||
|
appGui.parent = appsContainer
|
||||||
|
appGui:on("mouseLeftUp", function()
|
||||||
|
if not loading.visible then
|
||||||
|
loading.text = "Working..."
|
||||||
|
loading.visible = true
|
||||||
|
teverse.http:get("https://teverse.com/api/apps/" .. app.id .. "/script", {
|
||||||
|
["Authorization"] = "BEARER " .. teverse.userToken
|
||||||
|
}, function(code, body)
|
||||||
|
if code == 200 then
|
||||||
|
loading.visible = false
|
||||||
|
teverse.apps:loadString(body)
|
||||||
|
else
|
||||||
|
loading.text = "Unable to load app."
|
||||||
|
sleep(1.5)
|
||||||
|
loading.visible = false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
subtitle.text = "Server error."
|
subtitle.text = "Server error."
|
||||||
|
|
|
@ -18,7 +18,9 @@ return {
|
||||||
size = guiCoord(1/3, -20, 0, 70),
|
size = guiCoord(1/3, -20, 0, 70),
|
||||||
position = guiCoord(0, 10, 0, 60),
|
position = guiCoord(0, 10, 0, 60),
|
||||||
backgroundColour = colour.rgb(74, 140, 122),
|
backgroundColour = colour.rgb(74, 140, 122),
|
||||||
strokeRadius = 3
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.guiHelper
|
||||||
|
@ -71,7 +73,9 @@ return {
|
||||||
size = guiCoord(1/3, -20, 0, 70),
|
size = guiCoord(1/3, -20, 0, 70),
|
||||||
position = guiCoord(1/3, 10, 0, 0),
|
position = guiCoord(1/3, 10, 0, 0),
|
||||||
backgroundColour = colour.rgb(74, 140, 122),
|
backgroundColour = colour.rgb(74, 140, 122),
|
||||||
strokeRadius = 3
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.guiHelper
|
|
@ -0,0 +1,16 @@
|
||||||
|
return {
|
||||||
|
name = "Develop",
|
||||||
|
iconId = "layer-group",
|
||||||
|
iconType = "faSolid",
|
||||||
|
setup = function(page)
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = page,
|
||||||
|
size = guiCoord(1.0, -20, 0, 48),
|
||||||
|
position = guiCoord(0, 10, 0, 10),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = "Develop for Tablets is coming soon",
|
||||||
|
textSize = 48,
|
||||||
|
textAlign = "middleLeft"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
}
|
|
@ -1,4 +1,122 @@
|
||||||
local function newFeedItem(pfp, name, date, body)
|
-- Copyright 2020- Teverse.com
|
||||||
|
-- Used to display the home screen of the teverse application
|
||||||
|
|
||||||
|
local globals = require("tevgit:workshop/library/globals.lua") -- globals; variables or instances that can be shared between files
|
||||||
|
local modal = require("tevgit:workshop/library/ui/components/modal.lua") -- UI component
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
local function addTag(parent, icon, name, iconColour)
|
||||||
|
local frame = teverse.construct("guiFrame", {
|
||||||
|
parent = parent:child("_container"):child("_content"),
|
||||||
|
size = guiCoord(0.3, 0, 0.25, 0),
|
||||||
|
position = guiCoord(0, (count*43)+5, 0, 40),
|
||||||
|
backgroundColour = globals.defaultColours.white,
|
||||||
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.4,
|
||||||
|
dropShadowBlur = 2,
|
||||||
|
dropShadowColour = colour.rgb(127, 127, 127),
|
||||||
|
dropShadowOffset = vector2(0.5 , 1),
|
||||||
|
zIndex = 500
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiIcon", {
|
||||||
|
parent = frame,
|
||||||
|
size = guiCoord(0, 10, 0, 10),
|
||||||
|
position = guiCoord(0.05, 0, 0.21, 0),
|
||||||
|
iconType = "faSolid",
|
||||||
|
iconId = icon,
|
||||||
|
iconColour = iconColour
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = frame,
|
||||||
|
size = guiCoord(0.6, 0, 0.6, 0),
|
||||||
|
position = guiCoord(0.3, 0, 0.23, 0),
|
||||||
|
text = name,
|
||||||
|
textEditable = false,
|
||||||
|
textAlign = "middle",
|
||||||
|
textColour = globals.defaultColours.primary,
|
||||||
|
textSize = 12,
|
||||||
|
textWrap = false,
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
zIndex = 100
|
||||||
|
})
|
||||||
|
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function createFlair(parent, data)
|
||||||
|
local username = parent:child("username").text
|
||||||
|
if data then
|
||||||
|
local flairCount = 0
|
||||||
|
|
||||||
|
-- Beta(Tester) Insignia
|
||||||
|
if data.postedBy.beta == true then
|
||||||
|
teverse.construct("guiIcon", {
|
||||||
|
parent = parent:child("username"),
|
||||||
|
size = guiCoord(0, 10, 0, 10),
|
||||||
|
position = guiCoord(0, parent:child("username").textDimensions.x+((flairCount*10)+2), 0, 6),
|
||||||
|
iconType = "faSolid",
|
||||||
|
iconId = "flask",
|
||||||
|
iconColour = globals.defaultColours.red
|
||||||
|
})
|
||||||
|
addTag(parent, "flask", "BETA", globals.defaultColours.red)
|
||||||
|
flairCount = flairCount + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Plus Membership Insignia
|
||||||
|
if data.postedBy.membership == "plus" then
|
||||||
|
teverse.construct("guiIcon", {
|
||||||
|
parent = parent:child("username"),
|
||||||
|
size = guiCoord(0, 10, 0, 10),
|
||||||
|
position = guiCoord(0, parent:child("username").textDimensions.x+((flairCount*10)+2), 0, 6),
|
||||||
|
iconType = "faSolid",
|
||||||
|
iconId = "star",
|
||||||
|
iconColour = globals.defaultColours.primary
|
||||||
|
})
|
||||||
|
addTag(parent, "star", "PLUS", colour.rgb(67, 67, 67))
|
||||||
|
flairCount = flairCount + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pro Membership Insignia
|
||||||
|
if data.postedBy.membership == "pro" then
|
||||||
|
teverse.construct("guiIcon", {
|
||||||
|
parent = parent:child("username"),
|
||||||
|
size = guiCoord(0, 10, 0, 10),
|
||||||
|
position = guiCoord(0, parent:child("username").textDimensions.x+((flairCount*10)+2), 0, 6),
|
||||||
|
iconType = "faSolid",
|
||||||
|
iconId = "thermometer-full",
|
||||||
|
iconColour = globals.defaultColours.purple
|
||||||
|
})
|
||||||
|
parent:child("username").textColour = globals.defaultColours.purple
|
||||||
|
parent:child("body").textColour = globals.defaultColours.purple
|
||||||
|
addTag(parent, "thermometer-full", "PRO", globals.defaultColours.purple)
|
||||||
|
flairCount = flairCount + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mod/Staff Insignia
|
||||||
|
--[[
|
||||||
|
if then
|
||||||
|
teverse.construct("guiIcon", {
|
||||||
|
parent = parent:child("username"),
|
||||||
|
size = guiCoord(0, 10, 0, 10),
|
||||||
|
position = guiCoord(0, parent:child("username").textDimensions.x+((flairCount*10)+2), 0, 6),
|
||||||
|
iconType = "faSolid",
|
||||||
|
iconId = "shield-alt",
|
||||||
|
iconColour = globals.defaultColours.blue
|
||||||
|
})
|
||||||
|
parent:child("username").textColour = globals.defaultColours.blue
|
||||||
|
parent:child("body").textColour = globals.defaultColours.blue
|
||||||
|
addTag(parent, "shield-alt", "STAFF", globals.defaultColours.blue)
|
||||||
|
flairCount = flairCount + 1
|
||||||
|
end
|
||||||
|
]]--
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newFeedItem(date, data)
|
||||||
local item = teverse.construct("guiFrame", {
|
local item = teverse.construct("guiFrame", {
|
||||||
size = guiCoord(1, -20, 0, 48),
|
size = guiCoord(1, -20, 0, 48),
|
||||||
position = guiCoord(0, 10, 0, 40),
|
position = guiCoord(0, 10, 0, 40),
|
||||||
|
@ -10,22 +128,23 @@ local function newFeedItem(pfp, name, date, body)
|
||||||
name = "profilePicture",
|
name = "profilePicture",
|
||||||
size = guiCoord(0, 30, 0, 30),
|
size = guiCoord(0, 30, 0, 30),
|
||||||
position = guiCoord(0, 0, 0, 5),
|
position = guiCoord(0, 0, 0, 5),
|
||||||
image = pfp,
|
image = "tevurl:asset/user/"..(data.postedBy.id),
|
||||||
parent = item,
|
parent = item,
|
||||||
strokeRadius = 15,
|
strokeRadius = 15,
|
||||||
strokeAlpha = 0.04
|
strokeAlpha = 0.04
|
||||||
})
|
})
|
||||||
|
|
||||||
local name = teverse.construct("guiTextBox", {
|
local username = teverse.construct("guiTextBox", {
|
||||||
name = "username",
|
name = "username",
|
||||||
size = guiCoord(1, -40, 0, 20),
|
size = guiCoord(0.8, -50, 0, 20),
|
||||||
position = guiCoord(0, 40, 0, 3),
|
position = guiCoord(0, 40, 0, 3),
|
||||||
backgroundAlpha = 0,
|
backgroundAlpha = 0,
|
||||||
parent = item,
|
parent = item,
|
||||||
text = name,
|
text = data.postedBy.username,
|
||||||
textSize = 20,
|
textSize = 20,
|
||||||
textAlpha = 0.6,
|
textAlpha = 0.6,
|
||||||
textFont = "tevurl:fonts/openSansBold.ttf"
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
zIndex = 500
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.construct("guiTextBox", {
|
teverse.construct("guiTextBox", {
|
||||||
|
@ -47,12 +166,88 @@ local function newFeedItem(pfp, name, date, body)
|
||||||
position = guiCoord(0, 40, 0, 22),
|
position = guiCoord(0, 40, 0, 22),
|
||||||
backgroundAlpha = 0,
|
backgroundAlpha = 0,
|
||||||
parent = item,
|
parent = item,
|
||||||
text = body,
|
text = data.message,
|
||||||
textWrap = true,
|
textWrap = true,
|
||||||
textAlign = enums.align.topLeft,
|
textAlign = enums.align.topLeft,
|
||||||
textSize = 16
|
textSize = 16,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- Create User Modal (profile click/touch on feed)
|
||||||
|
local _modal = modal.construct(guiCoord(0, 130, 0, 60), guiCoord(0, 40, 0, 25))
|
||||||
|
_modal.content.parent = item
|
||||||
|
local content = teverse.construct("guiFrame", {
|
||||||
|
parent = _modal.content,
|
||||||
|
name = "_content",
|
||||||
|
position = guiCoord(0, 0, 0, 0),
|
||||||
|
size = guiCoord(1, 0, 1, 0),
|
||||||
|
backgroundColour = globals.defaultColours.white,
|
||||||
|
strokeColour = globals.defaultColours.white,
|
||||||
|
strokeRadius = 5,
|
||||||
|
strokeWidth = 1
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiImage", {
|
||||||
|
parent = content,
|
||||||
|
name = "profilePicture",
|
||||||
|
size = guiCoord(0, 32, 0, 32),
|
||||||
|
position = guiCoord(0, 3, 0, 6),
|
||||||
|
image = "tevurl:asset/user/"..(data.postedBy.id),
|
||||||
|
strokeRadius = 3,
|
||||||
|
backgroundColour = globals.defaultColours.white,
|
||||||
|
dropShadowAlpha = 0.4,
|
||||||
|
dropShadowBlur = 2,
|
||||||
|
dropShadowColour = colour.rgb(127, 127, 127),
|
||||||
|
dropShadowOffset = vector2(0.5, 1.5)
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = content,
|
||||||
|
name = "username",
|
||||||
|
size = guiCoord(0, 92, 0, 20),
|
||||||
|
position = guiCoord(0, 38, 0, 1),
|
||||||
|
text = data.postedBy.username,
|
||||||
|
textEditable = false,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textColour = globals.defaultColours.primary,
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
zIndex = 500
|
||||||
|
})
|
||||||
|
|
||||||
|
local messageButton = teverse.construct("guiTextBox", {
|
||||||
|
parent = content,
|
||||||
|
name = "messageButton",
|
||||||
|
size = guiCoord(0.68, 0, 0.25, 0),
|
||||||
|
position = guiCoord(0, 38, 0, 23),
|
||||||
|
text = "MESSAGE",
|
||||||
|
textEditable = false,
|
||||||
|
textAlign = "middle",
|
||||||
|
textColour = globals.defaultColours.primary,
|
||||||
|
textSize = 12,
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
backgroundColour = globals.defaultColours.white,
|
||||||
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.4,
|
||||||
|
dropShadowBlur = 2,
|
||||||
|
dropShadowColour = colour.rgb(127, 127, 127),
|
||||||
|
dropShadowOffset = vector2(0.5, 1),
|
||||||
|
zIndex = 500
|
||||||
|
})
|
||||||
|
|
||||||
|
-- When mouse hovers over label, display user modal
|
||||||
|
item:child("username"):on("mouseLeftDown", function()
|
||||||
|
_modal.display()
|
||||||
|
item.zIndex = 300
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- When mouse leaves from label, hide user modal
|
||||||
|
item:child("username"):on("mouseExit", function()
|
||||||
|
_modal.hide()
|
||||||
|
item.zIndex = 1
|
||||||
|
end)
|
||||||
|
|
||||||
|
createFlair(item, data)
|
||||||
|
|
||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,7 +262,8 @@ return {
|
||||||
size = guiCoord(1, 0, 1, 50),
|
size = guiCoord(1, 0, 1, 50),
|
||||||
position = guiCoord(0, 0, 0, -50),
|
position = guiCoord(0, 0, 0, -50),
|
||||||
backgroundAlpha = 0,
|
backgroundAlpha = 0,
|
||||||
strokeRadius = 3
|
strokeRadius = 3,
|
||||||
|
scrollbarWidth = 4
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.guiHelper
|
||||||
|
@ -87,7 +283,9 @@ return {
|
||||||
size = guiCoord(1/3, -20, 0, 70),
|
size = guiCoord(1/3, -20, 0, 70),
|
||||||
position = guiCoord(0, 10, 0, 0),
|
position = guiCoord(0, 10, 0, 0),
|
||||||
backgroundColour = colour.rgb(74, 140, 122),
|
backgroundColour = colour.rgb(74, 140, 122),
|
||||||
strokeRadius = 3
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.guiHelper
|
||||||
|
@ -144,7 +342,9 @@ return {
|
||||||
size = guiCoord(1/3, -20, 0, 70),
|
size = guiCoord(1/3, -20, 0, 70),
|
||||||
position = guiCoord(1/3, 10, 0, 0),
|
position = guiCoord(1/3, 10, 0, 0),
|
||||||
backgroundColour = colour.rgb(235, 187, 83),
|
backgroundColour = colour.rgb(235, 187, 83),
|
||||||
strokeRadius = 3
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.guiHelper
|
||||||
|
@ -209,7 +409,9 @@ return {
|
||||||
size = guiCoord(1/3, -20, 0, 70),
|
size = guiCoord(1/3, -20, 0, 70),
|
||||||
position = guiCoord(2/3, 10, 0, 0),
|
position = guiCoord(2/3, 10, 0, 0),
|
||||||
backgroundColour = colour.rgb(216, 100, 89),
|
backgroundColour = colour.rgb(216, 100, 89),
|
||||||
strokeRadius = 3
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.guiHelper
|
||||||
|
@ -272,7 +474,7 @@ return {
|
||||||
local feedItems = teverse.construct("guiFrame", {
|
local feedItems = teverse.construct("guiFrame", {
|
||||||
parent = feed,
|
parent = feed,
|
||||||
backgroundAlpha = 0,
|
backgroundAlpha = 0,
|
||||||
clip = true
|
clip = false
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.guiHelper
|
teverse.guiHelper
|
||||||
|
@ -291,12 +493,13 @@ return {
|
||||||
|
|
||||||
local input = teverse.construct("guiTextBox", {
|
local input = teverse.construct("guiTextBox", {
|
||||||
parent = feedItems,
|
parent = feedItems,
|
||||||
size = guiCoord(1, -20, 0, 30),
|
size = guiCoord(1, -2, 0, 30),
|
||||||
position = guiCoord(0, 10, 0, 10),
|
position = guiCoord(0, 1, 0, 10),
|
||||||
strokeAlpha = 0.15,
|
|
||||||
strokeRadius = 3,
|
|
||||||
textEditable = true,
|
textEditable = true,
|
||||||
textAlign = "topLeft"
|
textAlign = "topLeft",
|
||||||
|
strokeRadius = 2,
|
||||||
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05
|
||||||
})
|
})
|
||||||
|
|
||||||
local newestFeed = ""
|
local newestFeed = ""
|
||||||
|
@ -309,9 +512,9 @@ return {
|
||||||
}, function(code, body)
|
}, function(code, body)
|
||||||
if code == 200 then
|
if code == 200 then
|
||||||
lastRefresh = os.clock()
|
lastRefresh = os.clock()
|
||||||
local json = teverse.json:decode(body)
|
local data = teverse.json:decode(body)
|
||||||
if #json > 0 then
|
if #data > 0 then
|
||||||
if json[1].id == newestFeed then
|
if data[1].id == newestFeed then
|
||||||
-- no change from last refresh
|
-- no change from last refresh
|
||||||
return nil
|
return nil
|
||||||
else
|
else
|
||||||
|
@ -322,11 +525,11 @@ return {
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
newestFeed = json[1].id
|
newestFeed = data[1].id
|
||||||
local y = 50
|
local y = 50
|
||||||
for _,v in pairs(json) do
|
for _,v in pairs(data) do
|
||||||
local date = os.date("%d/%m/%Y %H:%M", os.parseISO8601(v.postedAt))
|
local date = os.date("%d/%m/%Y %H:%M", os.parseISO8601(v.postedAt))
|
||||||
local item = newFeedItem("tevurl:asset/user/" .. v.postedBy.id, v.postedBy.username, date, v.message)
|
local item = newFeedItem(date, v)
|
||||||
item.parent = feedItems
|
item.parent = feedItems
|
||||||
local dy = item:child("body").textDimensions.y
|
local dy = item:child("body").textDimensions.y
|
||||||
item.size = guiCoord(1, -20, 0, dy + 28)
|
item.size = guiCoord(1, -20, 0, dy + 28)
|
||||||
|
|
|
@ -113,16 +113,29 @@ controller.setup = function()
|
||||||
strokeRadius = 3
|
strokeRadius = 3
|
||||||
})
|
})
|
||||||
|
|
||||||
|
icon:on("mouseEnter", function()
|
||||||
|
icon.backgroundAlpha = 0.15
|
||||||
|
end)
|
||||||
|
|
||||||
|
icon:on("mouseExit", function()
|
||||||
|
-- container is visible if button is 'active'
|
||||||
|
if not container.visible then
|
||||||
|
icon.backgroundAlpha = 0
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
icon:on("mouseLeftUp", function()
|
icon:on("mouseLeftUp", function()
|
||||||
for _,v in pairs(pages) do
|
for _,v in pairs(pages) do
|
||||||
v[1].visible = false
|
v[1].visible = false
|
||||||
v[2].iconAlpha = 0.75
|
v[2].iconAlpha = 0.75
|
||||||
v[2].backgroundAlpha = 0.0
|
v[2].backgroundAlpha = 0.0
|
||||||
|
v[2].dropShadowAlpha = 0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
container.visible = true
|
container.visible = true
|
||||||
icon.iconAlpha = 1.0
|
icon.iconAlpha = 1.0
|
||||||
icon.backgroundAlpha = 0.2
|
icon.backgroundAlpha = 0.2
|
||||||
|
icon.dropShadowAlpha = 0.15
|
||||||
end)
|
end)
|
||||||
|
|
||||||
page.setup(container)
|
page.setup(container)
|
||||||
|
@ -138,8 +151,12 @@ controller.setup = function()
|
||||||
setupPage(require("tevgit:core/dashboard/pages/home.lua"))
|
setupPage(require("tevgit:core/dashboard/pages/home.lua"))
|
||||||
setupPage(require("tevgit:core/dashboard/pages/apps.lua"))
|
setupPage(require("tevgit:core/dashboard/pages/apps.lua"))
|
||||||
|
|
||||||
if _DEVICE:sub(0,6) ~= "iPhone" then
|
if _DEVICE:sub(0, 6) ~= "iPhone" then
|
||||||
setupPage(require("tevgit:core/dashboard/pages/develop.lua"))
|
if _DEVICE:sub(0, 4) == "iPad" then
|
||||||
|
--setupPage(require("tevgit:core/dashboard/pages/developTablet.lua"))
|
||||||
|
else
|
||||||
|
setupPage(require("tevgit:core/dashboard/pages/developDesktop.lua"))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
local lex = require("tevgit:core/editor/lexer.lua")
|
||||||
|
local theme = require("tevgit:core/editor/theme/default.lua")
|
||||||
|
|
||||||
|
return {
|
||||||
|
create = function()
|
||||||
|
local container = teverse.construct("guiRichTextBox", {
|
||||||
|
parent = teverse.interface,
|
||||||
|
size = guiCoord(1, 0, 1, 0),
|
||||||
|
position = guiCoord(0, 0, 0, 0),
|
||||||
|
backgroundColour = theme.background
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(1, -20, 0, 24),
|
||||||
|
position = guiCoord(0, 20, 0, 10),
|
||||||
|
text = "THIS IS A PROOF OF CONCEPT TEXT EDITOR\nWRITTEN USING OUR LUA API",
|
||||||
|
textSize = 12,
|
||||||
|
textColour = theme.foreground,
|
||||||
|
textAlpha = 0.5,
|
||||||
|
textWrap = true,
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
textFont = "tevurl:fonts/firaCodeBold.otf",
|
||||||
|
})
|
||||||
|
|
||||||
|
local numbers = teverse.construct("guiTextBox", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(0, 30, 1, -50),
|
||||||
|
position = guiCoord(0, 0, 0, 50),
|
||||||
|
text = "01",
|
||||||
|
textSize = 18,
|
||||||
|
textColour = theme.foreground,
|
||||||
|
textWrap = true,
|
||||||
|
backgroundColour = theme.highlighted,
|
||||||
|
textFont = "tevurl:fonts/firaCodeBold.otf",
|
||||||
|
textAlign = "topRight"
|
||||||
|
})
|
||||||
|
|
||||||
|
local editor = teverse.construct("guiRichTextBox", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(1, -35, 1, -50),
|
||||||
|
position = guiCoord(0, 35, 0, 50),
|
||||||
|
text = "print(\"Hello World\")\n\n",
|
||||||
|
textWrap = true,
|
||||||
|
textSize = 18,
|
||||||
|
textFont = "tevurl:fonts/firaCodeRegular.otf",
|
||||||
|
textEditable = true,
|
||||||
|
textMultiline = true,
|
||||||
|
name = "editor"
|
||||||
|
})
|
||||||
|
|
||||||
|
editor.backgroundColour = theme.background
|
||||||
|
editor.textColour = theme.foreground
|
||||||
|
|
||||||
|
local function doLex()
|
||||||
|
editor:clearColours()
|
||||||
|
|
||||||
|
local lines = lex(editor.text)
|
||||||
|
local index = 0
|
||||||
|
local lastColour = nil
|
||||||
|
local lineNumbers = ""
|
||||||
|
for lineNumber, line in pairs(lines) do
|
||||||
|
local lineCount = 0
|
||||||
|
for _, token in pairs(line) do
|
||||||
|
local c = theme[token.type]
|
||||||
|
if c and lastColour ~= c then
|
||||||
|
editor:setColour(index + token.posFirst, c)
|
||||||
|
lastColour = c
|
||||||
|
end
|
||||||
|
|
||||||
|
lineCount = token.posLast
|
||||||
|
end
|
||||||
|
index = index + lineCount
|
||||||
|
lineNumbers = lineNumbers .. string.format("%002d", lineNumber) .. "\n"
|
||||||
|
end
|
||||||
|
numbers.text = lineNumbers
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Highlight any pre-entered text
|
||||||
|
doLex()
|
||||||
|
|
||||||
|
local lastStroke = nil
|
||||||
|
local handler = function()
|
||||||
|
if lastStroke then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Limit lexxer to once very 0.1 seconds (every keystroke is inefficient)
|
||||||
|
lastStroke = true
|
||||||
|
doLex()
|
||||||
|
sleep(0.1)
|
||||||
|
lastStroke = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
editor:on("keyUp", handler)
|
||||||
|
editor:on("changed", handler)
|
||||||
|
|
||||||
|
return container, editor
|
||||||
|
end
|
||||||
|
}
|
|
@ -0,0 +1,431 @@
|
||||||
|
-- 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.
|
||||||
|
|
||||||
|
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'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return 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
|
|
@ -0,0 +1 @@
|
||||||
|
local editor = require("tevgit:core/editor/editor.lua").create()
|
|
@ -0,0 +1,45 @@
|
||||||
|
-- This file uses colours from https://ethanschoonover.com/solarized/
|
||||||
|
|
||||||
|
local colours = {
|
||||||
|
Base0 = colour.rgb(131, 148, 150),
|
||||||
|
Base1 = colour.rgb(147, 161, 161),
|
||||||
|
Base2 = colour.rgb(238, 232, 213),
|
||||||
|
Base3 = colour.rgb(253, 246, 227),
|
||||||
|
|
||||||
|
Base00 = colour.rgb(101, 123, 131),
|
||||||
|
Base01 = colour.rgb(88, 110, 117),
|
||||||
|
Base02 = colour.rgb(7, 54, 66),
|
||||||
|
Base03 = colour.rgb(0, 43, 54),
|
||||||
|
|
||||||
|
Yellow = colour.rgb(181, 137, 0),
|
||||||
|
Orange = colour.rgb(203, 75, 22),
|
||||||
|
Red = colour.rgb(220, 50, 47),
|
||||||
|
Magenta = colour.rgb(211, 54, 130),
|
||||||
|
Violet = colour.rgb(108, 113, 196),
|
||||||
|
Blue = colour.rgb(38, 139, 210),
|
||||||
|
Cyan = colour.rgb(42, 161, 152),
|
||||||
|
Green = colour.rgb(133, 153, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
background = colours.Base03,
|
||||||
|
foreground = colours.Base0,
|
||||||
|
highlighted = colours.Base02,
|
||||||
|
|
||||||
|
comment = colours.Base01,
|
||||||
|
string_start = colours.Cyan,
|
||||||
|
string_end = colours.Cyan,
|
||||||
|
string = colours.Cyan,
|
||||||
|
escape = colours.Blue,
|
||||||
|
keyword = colours.Magenta,
|
||||||
|
value = colours.Green,
|
||||||
|
ident = colours.Blue,
|
||||||
|
number = colours.Magenta,
|
||||||
|
symbol = colours.Base1,
|
||||||
|
vararg = colours.Red,
|
||||||
|
operator = colours.Green,
|
||||||
|
label_start = colours.Red,
|
||||||
|
label_end = colours.Red,
|
||||||
|
label = colours.Red,
|
||||||
|
unidentified = colours.Base01
|
||||||
|
}
|
|
@ -49,7 +49,13 @@ login.position = guiCoord(0.5, -50, 0.5, 45)
|
||||||
local db = false
|
local db = false
|
||||||
local listenerid = login:on("mouseLeftDown", function()
|
local listenerid = login:on("mouseLeftDown", function()
|
||||||
if db then return end
|
if db then return end
|
||||||
teverse.openUrl("https://teverse.com/dashboard?client=1")
|
|
||||||
|
if _DEVICE:sub(0, 6) == "iPhone" or _DEVICE:sub(0, 4) == "iPad" then
|
||||||
|
teverse.openUrl("https://teverse.com/dashboard?client=2")
|
||||||
|
else
|
||||||
|
teverse.openUrl("https://teverse.com/dashboard?client=1")
|
||||||
|
end
|
||||||
|
|
||||||
login.visible = false
|
login.visible = false
|
||||||
sleep(2)
|
sleep(2)
|
||||||
login.visible = true
|
login.visible = true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
local container = teverse.construct("guiFrame", {
|
local container = teverse.construct("guiFrame", {
|
||||||
parent = teverse.coreInterface,
|
parent = teverse.coreInterface,
|
||||||
size = guiCoord(0, 300, 0, 400),
|
size = guiCoord(0.1, 150, 0.4, 200),
|
||||||
position = guiCoord(0, 20, 0, 20),
|
position = guiCoord(0, 20, 0, 20),
|
||||||
backgroundAlpha = 0.9,
|
backgroundAlpha = 0.9,
|
||||||
zIndex = 1000,
|
zIndex = 1000,
|
||||||
|
@ -14,22 +14,58 @@ teverse.construct("guiTextBox", {
|
||||||
size = guiCoord(1, -10, 0, 20),
|
size = guiCoord(1, -10, 0, 20),
|
||||||
position = guiCoord(0, 5, 0, 0),
|
position = guiCoord(0, 5, 0, 0),
|
||||||
backgroundAlpha = 0.0,
|
backgroundAlpha = 0.0,
|
||||||
textSize = 16,
|
textSize = 20,
|
||||||
textAlign = "middleLeft",
|
textAlign = "middleLeft",
|
||||||
text = "Console"
|
text = "Console"
|
||||||
})
|
})
|
||||||
|
|
||||||
local txt = teverse.construct("guiTextBox", {
|
local logContainer = teverse.construct("guiScrollView", {
|
||||||
parent = container,
|
parent = container,
|
||||||
size = guiCoord(1, -10, 1, -25),
|
size = guiCoord(1, -10, 1, -22),
|
||||||
position = guiCoord(0, 5, 0, 20),
|
position = guiCoord(0, 5, 0, 20),
|
||||||
backgroundAlpha = 0.95,
|
backgroundAlpha = 0.0,
|
||||||
strokeAlpha = 0.2,
|
canvasSize = guiCoord(1, -1, 10, 0),
|
||||||
textWrap = true
|
scrollbarWidth = 3,
|
||||||
|
scrollbarRadius = 2
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local lastPos = 0
|
||||||
|
function addLog (msg, time)
|
||||||
|
local txt = teverse.construct("guiTextBox", {
|
||||||
|
parent = logContainer,
|
||||||
|
size = guiCoord(1, -10, 0, 25),
|
||||||
|
position = guiCoord(0, 5, 0, lastPos),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
strokeAlpha = 0,
|
||||||
|
textWrap = true,
|
||||||
|
clip = false
|
||||||
|
})
|
||||||
|
txt.text = os.date("%H:%M:%S", time) .. " : " .. msg
|
||||||
|
txt.size = guiCoord(1, -10, 0, txt.textDimensions.y)
|
||||||
|
lastPos = lastPos + txt.textDimensions.y + 3
|
||||||
|
|
||||||
|
if string.find(msg, "ERROR:") then
|
||||||
|
txt.textColour = colour.rgb(220, 50, 47)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update container size
|
||||||
|
logContainer.canvasSize = guiCoord(1, -1, 0.5, lastPos)
|
||||||
|
end
|
||||||
|
-- TODO: Warn/error detection & colours
|
||||||
teverse.debug:on("print", function(msg)
|
teverse.debug:on("print", function(msg)
|
||||||
txt.text = string.sub(os.date("%H:%M:%S") .. " : " .. msg .. "\n" .. txt.text, 0, 500)
|
pcall(function()
|
||||||
|
addLog(msg)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
if _TEV_VERSION_PATCH and _TEV_VERSION_PATCH >= 9 then
|
||||||
|
for _,v in pairs(teverse.debug:getOutputHistory()) do
|
||||||
|
addLog(v.message, v.time)
|
||||||
|
end
|
||||||
|
logContainer.canvasOffset = vector2(0, lastPos - 200)
|
||||||
|
else
|
||||||
|
print("History not supported")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
return container
|
return container
|
|
@ -1,82 +1,90 @@
|
||||||
-- This is the main interface loaded into coreinterface
|
-- This is the main interface loaded into coreinterface
|
||||||
local console = require("tevgit:core/teverseUI/console.lua")
|
|
||||||
|
|
||||||
local container = teverse.construct("guiFrame", {
|
-- status bar for mobiles:
|
||||||
|
teverse.construct("guiFrame", {
|
||||||
|
name = "statusBar",
|
||||||
parent = teverse.coreInterface,
|
parent = teverse.coreInterface,
|
||||||
size = guiCoord(0, 77, 0, 26),
|
size = guiCoord(1, 0, 0, 50),
|
||||||
position = guiCoord(1, -81, 1, -30),
|
position = guiCoord(0, 0, 0, -50),
|
||||||
backgroundAlpha = 0.0,
|
backgroundColour = colour.black(),
|
||||||
strokeRadius = 13,
|
backgroundAlpha = 0.75
|
||||||
zIndex = 1000
|
|
||||||
})
|
})
|
||||||
|
|
||||||
local homebtn
|
if teverse.dev.localTevGit then
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = teverse.coreInterface,
|
||||||
|
size = guiCoord(0,60, 0, 12),
|
||||||
|
position = guiCoord(1, -70, 1, -59),
|
||||||
|
zIndex = 1000,
|
||||||
|
textSize = 12,
|
||||||
|
text = "Local TevGit",
|
||||||
|
textAlign = "middleRight",
|
||||||
|
textAlpha = 0.5,
|
||||||
|
backgroundAlpha = 0
|
||||||
|
})
|
||||||
|
elseif _TEV_VERSION_PATCH and _TEV_VERSION_PATCH >= 12 then
|
||||||
|
teverse.input:on("keyUp", function(key)
|
||||||
|
if key == "KEY_F1" and not teverse.dev.localTevGit and teverse.input:isKeyDown("KEY_LSHIFT") then
|
||||||
|
teverse.dev:promptTevGit()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
local ico = teverse.construct("guiIcon", {
|
local settingsButton = teverse.construct("guiIcon", {
|
||||||
parent = container,
|
parent = teverse.coreInterface,
|
||||||
size = guiCoord(0, 20, 0, 20),
|
size = guiCoord(0, 35, 0, 35),
|
||||||
position = guiCoord(1, -23, 0.5, -10),
|
position = guiCoord(1, -45, 1, -45),
|
||||||
iconId = "wrench",
|
iconId = "wrench",
|
||||||
iconType = "faSolid",
|
iconType = "faSolid",
|
||||||
iconColour = colour(0, 0, 0),
|
iconColour = colour(0, 0, 0),
|
||||||
iconMax = 12,
|
iconMax = 12,
|
||||||
iconAlpha = 0.75,
|
iconAlpha = 0.75,
|
||||||
strokeRadius = 10,
|
strokeRadius = 2,
|
||||||
strokeAlpha = 0.5,
|
dropShadowAlpha = 0.15,
|
||||||
|
strokeAlpha = 0.05,
|
||||||
backgroundAlpha = 1,
|
backgroundAlpha = 1,
|
||||||
visible = teverse.networking.localClient ~= nil
|
visible = teverse.networking.localClient ~= nil,
|
||||||
|
zIndex = 1000
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local container = teverse.construct("guiFrame", {
|
||||||
|
parent = teverse.coreInterface,
|
||||||
|
size = guiCoord(0, 100, 0, 35),
|
||||||
|
position = guiCoord(1, -155, 1, -45),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
visible = false
|
||||||
|
})
|
||||||
|
|
||||||
|
local console = require("tevgit:core/teverseUI/console.lua")
|
||||||
local lastClick = 0
|
local lastClick = 0
|
||||||
ico:on("mouseLeftDown", function()
|
settingsButton:on("mouseLeftUp", function()
|
||||||
if os.clock() - lastClick < 0.4 then
|
if os.clock() - lastClick < 0.4 then
|
||||||
-- double click
|
-- double click
|
||||||
lastClick = 0
|
lastClick = 0
|
||||||
console.visible = not console.visible
|
console.visible = not console.visible
|
||||||
else
|
else
|
||||||
lastClick = os.clock()
|
lastClick = os.clock()
|
||||||
|
container.visible = true
|
||||||
|
repeat sleep(0.1) until teverse.input.mousePosition.y < container.absolutePosition.y - 25
|
||||||
|
container.visible = false
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--if teverse.dev.localTevGit then
|
local homeButton = teverse.construct("guiIcon", {
|
||||||
|
|
||||||
homebtn = teverse.construct("guiTextBox", {
|
|
||||||
parent = container,
|
parent = container,
|
||||||
size = guiCoord(0, 40, 0, 14),
|
size = guiCoord(0, 35, 0, 35),
|
||||||
position = guiCoord(0, 6, 0.5, -7),
|
position = guiCoord(1, -35, 0, 0),
|
||||||
text = "HOME",
|
iconId = "home",
|
||||||
textAlign = "middle",
|
iconType = "faSolid",
|
||||||
textFont = "tevurl:fonts/openSansLight.ttf",
|
iconColour = colour(0, 0, 0),
|
||||||
textColour = colour(0, 0, 0),
|
iconMax = 12,
|
||||||
textSize = 14,
|
iconAlpha = 0.75,
|
||||||
strokeRadius = 7,
|
strokeRadius = 2,
|
||||||
strokeAlpha = 0.5,
|
dropShadowAlpha = 0.15,
|
||||||
backgroundAlpha = 0,
|
strokeAlpha = 0.05,
|
||||||
visible = false
|
backgroundAlpha = 1
|
||||||
})
|
})
|
||||||
|
|
||||||
homebtn:on("mouseLeftUp", function()
|
homeButton:on("mouseLeftUp", function()
|
||||||
teverse.apps:loadDashboard()
|
teverse.apps:loadDashboard()
|
||||||
end)
|
|
||||||
|
|
||||||
ico:on("mouseLeftUp", function()
|
|
||||||
container.backgroundAlpha = 1.0
|
|
||||||
homebtn.visible = true
|
|
||||||
|
|
||||||
if teverse.dev.state == "dashboard" then
|
|
||||||
if teverse.dev.localTevGit then
|
|
||||||
homebtn.text = "RESET"
|
|
||||||
homebtn.visible = true
|
|
||||||
else
|
|
||||||
homebtn.visible = false
|
|
||||||
end
|
|
||||||
else
|
|
||||||
homebtn.text = "HOME"
|
|
||||||
homebtn.visible = true
|
|
||||||
end
|
|
||||||
|
|
||||||
repeat sleep(0.1) until teverse.input.mousePosition.y < container.absolutePosition.y - 25
|
|
||||||
|
|
||||||
container.backgroundAlpha = 0.0
|
|
||||||
homebtn.visible = false
|
|
||||||
end)
|
end)
|
|
@ -0,0 +1,27 @@
|
||||||
|
return {
|
||||||
|
titleDesc = function(title, description)
|
||||||
|
return {
|
||||||
|
type = "titleDesc",
|
||||||
|
title = title,
|
||||||
|
description = description
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
interactiveCode = function(title, description, code, validator)
|
||||||
|
return {
|
||||||
|
type = "titleDescCode",
|
||||||
|
title = title,
|
||||||
|
description = description,
|
||||||
|
code = code,
|
||||||
|
validator = validator
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
exampleCode = function(title, description, code, exampleOutput)
|
||||||
|
return {
|
||||||
|
type = "exampleCode",
|
||||||
|
title = title,
|
||||||
|
description = description,
|
||||||
|
code = code,
|
||||||
|
output = exampleOutput
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
return {
|
||||||
|
require("tevgit:core/tutorials/lessons/helloworld.lua"),
|
||||||
|
require("tevgit:core/tutorials/lessons/simplemaths.lua"),
|
||||||
|
require("tevgit:core/tutorials/lessons/variables.lua")
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
local framework = require("tevgit:core/tutorials/framework.lua")
|
||||||
|
|
||||||
|
return {
|
||||||
|
name = "Hello World",
|
||||||
|
description = "A very quick and simple introduction, you can start here.",
|
||||||
|
pages = {
|
||||||
|
framework.interactiveCode(
|
||||||
|
"Saying Hello to the World ",
|
||||||
|
[[Let's jump straight into writing your first script!
|
||||||
|
|
||||||
|
Type Hello World between the two quotation marks, then press run]],
|
||||||
|
[[print("")]],
|
||||||
|
function(script, logs)
|
||||||
|
local correct = script.text:lower() == "print(\"hello world\")"
|
||||||
|
if not correct then
|
||||||
|
print("Try again thats not quite right...\n")
|
||||||
|
else
|
||||||
|
print("Well done! Press next!\n")
|
||||||
|
end
|
||||||
|
return correct
|
||||||
|
end
|
||||||
|
),
|
||||||
|
framework.exampleCode(
|
||||||
|
"Dissecting your script",
|
||||||
|
[[A function contains a set of commands that the system follows.
|
||||||
|
|
||||||
|
You ran the 'print' function and you passed the parameter "Hello World" to it.
|
||||||
|
|
||||||
|
The print function simply outputs the stuff you give it to the console. The console is what you seen on the right of the screen.
|
||||||
|
|
||||||
|
Example Output from the script on the left:]],
|
||||||
|
[[print("Hello World")
|
||||||
|
|
||||||
|
print("We can put anything here")
|
||||||
|
]],
|
||||||
|
[[Hello World
|
||||||
|
We can put anything here
|
||||||
|
]]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
local framework = require("tevgit:core/tutorials/framework.lua")
|
||||||
|
|
||||||
|
return {
|
||||||
|
name = "Simple Mathematics",
|
||||||
|
description = "Simple mathematic operations",
|
||||||
|
pages = {
|
||||||
|
framework.exampleCode("Arithmetic Operators",
|
||||||
|
[[Arithmetic operations are sometimes necessary to determine how to handle arguments or conditions.
|
||||||
|
|
||||||
|
Lua can handle the typical maths operators:
|
||||||
|
"+" for addition, "-" for subtractions, "*" for multiplication, and "/" for division.
|
||||||
|
|
||||||
|
For our example, we are using the 'print()' function to display the results of these maths operations.
|
||||||
|
The console is what you see on the right of the screen.
|
||||||
|
|
||||||
|
When you're ready to continue, press next at the bottom of your screen.
|
||||||
|
|
||||||
|
Example Output from the script on the left:]],
|
||||||
|
[[--Addition
|
||||||
|
print(1+2)
|
||||||
|
--Subtraction
|
||||||
|
print(3-1)
|
||||||
|
--Multiplication
|
||||||
|
print(4*2)
|
||||||
|
--Division
|
||||||
|
print(2/1)
|
||||||
|
]],
|
||||||
|
[[
|
||||||
|
3
|
||||||
|
2
|
||||||
|
8
|
||||||
|
2
|
||||||
|
]]),
|
||||||
|
framework.interactiveCode("Try it: Arithmetic Operations",
|
||||||
|
[[Now that you know the basic operators, let's try to use them.
|
||||||
|
For each of the following samples, make the output equal 20, using the operation in between the two quotation marks.
|
||||||
|
You may need to include numbers as well. When you think you have it, press run.]],
|
||||||
|
[[print(12 "addition" __ )
|
||||||
|
|
||||||
|
-- Friendly reminder: print(1 + 1) will display 2]],
|
||||||
|
function(script, logs)
|
||||||
|
local answer = "print(12+8)"
|
||||||
|
local correct = script.text:lower():gsub(" ", ""):sub(0, answer:len()) == answer
|
||||||
|
if not correct then
|
||||||
|
print("Try again thats not quite right...\n")
|
||||||
|
else
|
||||||
|
print("Well done! Press next!\n")
|
||||||
|
end
|
||||||
|
return correct
|
||||||
|
end),
|
||||||
|
framework.interactiveCode("Try it: Arithmetic Operations",
|
||||||
|
[[Now that you know the basic operators, let's try to use them.
|
||||||
|
For each of the following samples, make the output equal 20, using the operation in between the two quotation marks.
|
||||||
|
You may need to include numbers as well. When you think you have it, press run.]],
|
||||||
|
[[print(2000 "division" __ )]],
|
||||||
|
function(script, logs)
|
||||||
|
local answer = "print(2000/100)"
|
||||||
|
local correct = script.text:lower():gsub(" ", ""):sub(0, answer:len()) == answer
|
||||||
|
if not correct then
|
||||||
|
print("Try again thats not quite right...\n")
|
||||||
|
else
|
||||||
|
print("Well done! Press next!\n")
|
||||||
|
end
|
||||||
|
return correct
|
||||||
|
end),
|
||||||
|
framework.interactiveCode("Try it: Arithmetic Operations",
|
||||||
|
[[Now that you know the basic operators, let's try to use them.
|
||||||
|
For each of the following samples, make the output equal 20, using the operation in between the two quotation marks.
|
||||||
|
You may need to include numbers as well. When you think you have it, press run.]],
|
||||||
|
[[print(10 "multiplication" __ )]],
|
||||||
|
function(script, logs)
|
||||||
|
local answer = "print(10*2)"
|
||||||
|
local correct = script.text:lower():gsub(" ", ""):sub(0, answer:len()) == answer
|
||||||
|
if not correct then
|
||||||
|
print("Try again thats not quite right...\n")
|
||||||
|
else
|
||||||
|
print("Well done! Press next!\n")
|
||||||
|
end
|
||||||
|
return correct
|
||||||
|
end),
|
||||||
|
framework.interactiveCode("Try it: Arithmetic Operations",
|
||||||
|
[[Now that you know the basic operators, let's try to use them.
|
||||||
|
For each of the following samples, make the output equal 20, using the operation in between the two quotation marks.
|
||||||
|
You may need to include numbers as well. When you think you have it, press run.]],
|
||||||
|
[[print(__ "subtraction" 40)]],
|
||||||
|
function(script, logs)
|
||||||
|
local answer = "print(60-40)"
|
||||||
|
local correct = script.text:lower():gsub(" ", ""):sub(0, answer:len()) == answer
|
||||||
|
if not correct then
|
||||||
|
print("Try again thats not quite right...\n")
|
||||||
|
else
|
||||||
|
print("Well done! Press next!\n")
|
||||||
|
end
|
||||||
|
return correct
|
||||||
|
end),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
local framework = require("tevgit:core/tutorials/framework.lua")
|
||||||
|
|
||||||
|
return {
|
||||||
|
name = "Variables",
|
||||||
|
description = "Learning Variables",
|
||||||
|
pages = {
|
||||||
|
framework.interactiveCode("Naming things in our world ",
|
||||||
|
[[Variables are a way of storing data in your code. In Lua, a variable can contain any 'type' - for example: numbers, strings and tables.
|
||||||
|
|
||||||
|
Try pressing run right now and take note of what displays in the console.
|
||||||
|
|
||||||
|
Then type testVariable between the two quotation marks, and press run again]],
|
||||||
|
[[local newVariable = "example"
|
||||||
|
|
||||||
|
print(newVariable)]],
|
||||||
|
function(script, logs)
|
||||||
|
local answer = "localnewvariable=\"testvariable\""
|
||||||
|
local correct = script.text:lower():gsub(" ", ""):sub(0, answer:len()) == answer
|
||||||
|
if not correct then
|
||||||
|
local answer = "localnewvariable=\"example\""
|
||||||
|
correct = script.text:lower():gsub(" ", ""):sub(0, answer:len()) == answer
|
||||||
|
if correct then
|
||||||
|
print("As you can see, print(newVariable) displays the contents of the variable - AKA: example\n\nChange the value from example to testVariable\n")
|
||||||
|
else
|
||||||
|
print("Try again!\n")
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
print("Well done, isn't setting variables a blast? Press next!\n")
|
||||||
|
end
|
||||||
|
return correct
|
||||||
|
end),
|
||||||
|
framework.exampleCode("Dissecting your script",
|
||||||
|
[[A variable is a way to assign a name to something.
|
||||||
|
|
||||||
|
Variables can come in the form of multiple types: strings, numbers, booleans, tables, functions, and much more!
|
||||||
|
|
||||||
|
In the first section, you declared the variable "newVariable" as a string "testVariable"; a string is usually a phrase or non-numeric set of characters.
|
||||||
|
|
||||||
|
The print function simply outputs the variables in the console. The console is what you see on the right of the screen.
|
||||||
|
|
||||||
|
When you're ready to continue, press next at the bottom of your screen.
|
||||||
|
|
||||||
|
Example Output from the script on the left:]],
|
||||||
|
[[local newPhrase = "This is a string"
|
||||||
|
local newNumber = 4
|
||||||
|
|
||||||
|
print(newPhrase)
|
||||||
|
print(newNumber)
|
||||||
|
|
||||||
|
]], [["This is a string"
|
||||||
|
4
|
||||||
|
]]),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,339 @@
|
||||||
|
local containerNegativePadding = teverse.construct("guiFrame", {
|
||||||
|
parent = teverse.interface,
|
||||||
|
size = guiCoord(1, 0, 1, 100),
|
||||||
|
position = guiCoord(0, 0, 0, -50)
|
||||||
|
})
|
||||||
|
|
||||||
|
local container = teverse.construct("guiScrollView", {
|
||||||
|
parent = containerNegativePadding,
|
||||||
|
size = guiCoord(1, 0, 1, -100),
|
||||||
|
position = guiCoord(0, 0, 0, 50),
|
||||||
|
canvasSize = guiCoord(1, 0, 1, 0),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
scrollbarWidth = 4
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(1.0, -20, 0, 48),
|
||||||
|
position = guiCoord(0, 10, 0, 10),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = "Learn Code",
|
||||||
|
textSize = 48,
|
||||||
|
textAlign = "middleLeft"
|
||||||
|
})
|
||||||
|
|
||||||
|
local y = 70
|
||||||
|
|
||||||
|
local function loadTutorialPage(tutorial, pagei, lessonFrame)
|
||||||
|
lessonFrame:destroyChildren()
|
||||||
|
local page = tutorial.pages[pagei]
|
||||||
|
local allowContinue = true
|
||||||
|
local btn = nil
|
||||||
|
|
||||||
|
if page.type == "titleDesc" then
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(1.0, -20, 0, 32),
|
||||||
|
position = guiCoord(0, 10, 0, 10),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = page.title,
|
||||||
|
textSize = 32,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf"
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(1.0, -20, 1, -50),
|
||||||
|
position = guiCoord(0, 10, 0, 42),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = page.description,
|
||||||
|
textSize = 18,
|
||||||
|
textAlign = "topLeft",
|
||||||
|
textWrap = true
|
||||||
|
})
|
||||||
|
elseif page.type == "titleDescCode" then
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(1.0, -20, 0, 32),
|
||||||
|
position = guiCoord(0, 10, 0, 10),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = page.title,
|
||||||
|
textSize = 32,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf"
|
||||||
|
})
|
||||||
|
|
||||||
|
local desc = teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(1.0, -20, 1, -50),
|
||||||
|
position = guiCoord(0, 10, 0, 42),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = page.description,
|
||||||
|
textSize = 18,
|
||||||
|
textAlign = "topLeft",
|
||||||
|
textWrap = true
|
||||||
|
})
|
||||||
|
|
||||||
|
local textDimensions = desc.textDimensions.y
|
||||||
|
desc.size = guiCoord(1, -20, 0, textDimensions)
|
||||||
|
|
||||||
|
local output, outputtxt = require("tevgit:core/tutorials/output.lua").create()
|
||||||
|
output.parent = lessonFrame
|
||||||
|
output.position = guiCoord(0.5, 10, 0, textDimensions + 52)
|
||||||
|
output.size = guiCoord(0.5, -20, 1, -(textDimensions + 102))
|
||||||
|
|
||||||
|
local editor, editortxt = require("tevgit:core/editor/editor.lua").create()
|
||||||
|
editor.parent = lessonFrame
|
||||||
|
editor.position = guiCoord(0, 10, 0, textDimensions + 52)
|
||||||
|
editor.size = guiCoord(0.5, -20, 1, -(textDimensions + 102))
|
||||||
|
editortxt.text = page.code
|
||||||
|
|
||||||
|
teverse.guiHelper.bind(editor, "xs", {
|
||||||
|
size = guiCoord(1.0, -20, 0.5, -52)
|
||||||
|
}).bind(editor, "md", {
|
||||||
|
size = guiCoord(0.5, -20, 1, -(textDimensions + 102))
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.guiHelper.bind(output, "xs", {
|
||||||
|
size = guiCoord(1.0, -20, 0.5, -(textDimensions + 60)),
|
||||||
|
position = guiCoord(0, 10, 0.5, textDimensions + 10)
|
||||||
|
}).bind(output, "md", {
|
||||||
|
size = guiCoord(0.5, -20, 1, -(textDimensions + 102)),
|
||||||
|
position = guiCoord(0.5, 10, 0, textDimensions + 52)
|
||||||
|
})
|
||||||
|
|
||||||
|
local run = teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(0, 90, 0, 30),
|
||||||
|
position = guiCoord(1, -235, 1, -35),
|
||||||
|
text = "Run",
|
||||||
|
textSize = 24,
|
||||||
|
textAlign = "middle",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
backgroundColour = colour.rgb(74, 140, 122),
|
||||||
|
textColour = colour.white(),
|
||||||
|
dropShadowAlpha = 0.2
|
||||||
|
})
|
||||||
|
teverse.guiHelper.hoverColour(run, colour.rgb(235, 187, 83))
|
||||||
|
|
||||||
|
local reset = teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(0, 90, 0, 30),
|
||||||
|
position = guiCoord(1, -340, 1, -35),
|
||||||
|
text = "Reset",
|
||||||
|
textSize = 24,
|
||||||
|
textAlign = "middle",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
backgroundColour = colour.rgb(74, 140, 122),
|
||||||
|
textColour = colour.white(),
|
||||||
|
dropShadowAlpha = 0.2
|
||||||
|
})
|
||||||
|
teverse.guiHelper.hoverColour(reset, colour.rgb(235, 187, 83))
|
||||||
|
allowContinue = false
|
||||||
|
|
||||||
|
run:on("mouseLeftUp", function()
|
||||||
|
outputtxt.text = ""
|
||||||
|
local f, msg = loadstring(editortxt.text)
|
||||||
|
if not f then
|
||||||
|
outputtxt.text = "Error when running your code:\n"..msg
|
||||||
|
else
|
||||||
|
local success, result = pcall(f)
|
||||||
|
if not success then
|
||||||
|
outputtxt.text = "Error when running your code:\n"..result
|
||||||
|
else
|
||||||
|
if page.validator then
|
||||||
|
allowContinue = page.validator(editortxt, outputtxt)
|
||||||
|
else
|
||||||
|
allowContinue = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if allowContinue and btn then
|
||||||
|
btn.backgroundColour = colour.rgb(235, 187, 83)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
reset:on("mouseLeftUp", function()
|
||||||
|
outputtxt.text = ""
|
||||||
|
editortxt.text = page.code
|
||||||
|
end)
|
||||||
|
elseif page.type == "exampleCode" then
|
||||||
|
local editor, editortxt = require("tevgit:core/editor/editor.lua").create()
|
||||||
|
editor.parent = lessonFrame
|
||||||
|
editor.position = guiCoord(0, 10, 0, 10)
|
||||||
|
editor.size = guiCoord(0.5, -20, 1, -20)
|
||||||
|
editortxt.text = page.code
|
||||||
|
editortxt.textEditable = false
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(0.5, -20, 0, 32),
|
||||||
|
position = guiCoord(0.5, 10, 0, 10),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = page.title,
|
||||||
|
textSize = 32,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf"
|
||||||
|
})
|
||||||
|
|
||||||
|
local desc = teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(0.5, -20, 1, -100),
|
||||||
|
position = guiCoord(0.5, 10, 0, 42),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = page.description,
|
||||||
|
textSize = 18,
|
||||||
|
textAlign = "topLeft",
|
||||||
|
textWrap = true,
|
||||||
|
active = false
|
||||||
|
})
|
||||||
|
|
||||||
|
if page.output then
|
||||||
|
local descDimensions = desc.textDimensions
|
||||||
|
local output, outputtxt = require("tevgit:core/tutorials/output.lua").create(true)
|
||||||
|
outputtxt.text = page.output
|
||||||
|
output.parent = lessonFrame
|
||||||
|
output.position = guiCoord(0.5, 10, 0, descDimensions.y + 45)
|
||||||
|
output.size = guiCoord(0.5, -20, 0, outputtxt.textDimensions.y + 44)
|
||||||
|
end
|
||||||
|
allowContinue = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if pagei == #tutorial.pages then
|
||||||
|
btn = teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(0, 90, 0, 30),
|
||||||
|
position = guiCoord(1, -140, 1, -35),
|
||||||
|
text = "Finished",
|
||||||
|
textSize = 20,
|
||||||
|
textAlign = "middle",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
backgroundColour = colour.rgb(122, 122, 122),
|
||||||
|
textColour = colour.white(),
|
||||||
|
dropShadowAlpha = 0.2
|
||||||
|
})
|
||||||
|
|
||||||
|
btn:on("mouseLeftUp", function()
|
||||||
|
reload()
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
btn = teverse.construct("guiTextBox", {
|
||||||
|
parent = lessonFrame,
|
||||||
|
size = guiCoord(0, 80, 0, 30),
|
||||||
|
position = guiCoord(1, -130, 1, -35),
|
||||||
|
text = "Next",
|
||||||
|
textSize = 24,
|
||||||
|
textAlign = "middle",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
backgroundColour = allowContinue and colour.rgb(74, 140, 122) or colour.rgb(122, 122, 122),
|
||||||
|
textColour = colour.white(),
|
||||||
|
dropShadowAlpha = 0.2
|
||||||
|
})
|
||||||
|
|
||||||
|
btn:on("mouseLeftUp", function()
|
||||||
|
if allowContinue then
|
||||||
|
loadTutorialPage(tutorial, pagei + 1, lessonFrame)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
btn:on("mouseEnter", function()
|
||||||
|
if allowContinue then
|
||||||
|
btn.backgroundColour = colour.rgb(235, 187, 83)
|
||||||
|
else
|
||||||
|
btn.backgroundColour = colour.rgb(122, 122, 122)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
btn:on("mouseExit", function()
|
||||||
|
if allowContinue then
|
||||||
|
btn.backgroundColour = colour.rgb(74, 140, 122)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function loadTutorial(tutorial)
|
||||||
|
container:destroyChildren()
|
||||||
|
|
||||||
|
local lessonFrame = teverse.construct("guiFrame", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(1.0, -20, 1, 0),
|
||||||
|
position = guiCoord(0, 10, 0, 0),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[teverse.construct("guiIcon", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(0, 30, 0, 30),
|
||||||
|
position = guiCoord(1, -40, 0, 10),
|
||||||
|
iconType = "faSolid",
|
||||||
|
iconId = "arrow-circle-left",
|
||||||
|
iconColour = colour.black(),
|
||||||
|
iconMax = 20,
|
||||||
|
backgroundAlpha = 0.05,
|
||||||
|
backgroundColour = colour.black(),
|
||||||
|
strokeRadius = 4
|
||||||
|
})]]
|
||||||
|
|
||||||
|
loadTutorialPage(tutorial, 1, lessonFrame)
|
||||||
|
end
|
||||||
|
|
||||||
|
for i,v in pairs(require("tevgit:core/tutorials/lessons.lua")) do
|
||||||
|
local lesson = teverse.construct("guiFrame", {
|
||||||
|
parent = container,
|
||||||
|
position = guiCoord(0, 10, 0, y),
|
||||||
|
size = guiCoord(1, -20, 0, 50),
|
||||||
|
backgroundColour = colour.rgb(245, 245, 245),
|
||||||
|
dropShadowAlpha = 0.2,
|
||||||
|
strokeRadius = 3
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.guiHelper.hoverColour(lesson, colour.white())
|
||||||
|
lesson:on("mouseLeftUp", function()
|
||||||
|
loadTutorial(v)
|
||||||
|
end)
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = lesson,
|
||||||
|
size = guiCoord(0, 40, 1, -10),
|
||||||
|
position = guiCoord(0, 5, 0, 5),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = string.format("%02d", i),
|
||||||
|
textSize = 32,
|
||||||
|
textAlign = "middle",
|
||||||
|
textFont = "tevurl:fonts/firaCodeMedium.otf",
|
||||||
|
textColour = colour.rgb(211, 54, 130),
|
||||||
|
active = false
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = lesson,
|
||||||
|
size = guiCoord(1.0, -60, 0, 22),
|
||||||
|
position = guiCoord(0, 50, 0, 5),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = v.name,
|
||||||
|
textSize = 22,
|
||||||
|
textAlign = "middleLeft",
|
||||||
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
|
active = false
|
||||||
|
})
|
||||||
|
|
||||||
|
local desc = teverse.construct("guiTextBox", {
|
||||||
|
parent = lesson,
|
||||||
|
size = guiCoord(1.0, -60, 1, -25),
|
||||||
|
position = guiCoord(0, 50, 0, 25),
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
text = v.description,
|
||||||
|
textSize = 18,
|
||||||
|
textAlign = "topLeft",
|
||||||
|
textWrap = true,
|
||||||
|
active = false
|
||||||
|
})
|
||||||
|
|
||||||
|
lesson.size = guiCoord(1, -20, 0, 29 + desc.textDimensions.y)
|
||||||
|
|
||||||
|
y = y + 25 + desc.textDimensions.y + 15
|
||||||
|
end
|
|
@ -0,0 +1,48 @@
|
||||||
|
local theme = require("tevgit:core/editor/theme/default.lua")
|
||||||
|
|
||||||
|
return {
|
||||||
|
create = function(doNotHook)
|
||||||
|
local container = teverse.construct("guiRichTextBox", {
|
||||||
|
parent = teverse.interface,
|
||||||
|
size = guiCoord(1, 0, 1, 0),
|
||||||
|
position = guiCoord(0, 0, 0, 0),
|
||||||
|
backgroundColour = theme.background
|
||||||
|
})
|
||||||
|
|
||||||
|
teverse.construct("guiTextBox", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(1, -20, 0, 12),
|
||||||
|
position = guiCoord(0, 20, 0, 10),
|
||||||
|
text = "OUTPUT",
|
||||||
|
textSize = 12,
|
||||||
|
textColour = theme.foreground,
|
||||||
|
textWrap = true,
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
textFont = "tevurl:fonts/firaCodeBold.otf",
|
||||||
|
})
|
||||||
|
|
||||||
|
local text = teverse.construct("guiRichTextBox", {
|
||||||
|
parent = container,
|
||||||
|
size = guiCoord(1, -40, 1, -34),
|
||||||
|
position = guiCoord(0, 20, 0, 34),
|
||||||
|
text = "",
|
||||||
|
textWrap = true,
|
||||||
|
textSize = 18,
|
||||||
|
textFont = "tevurl:fonts/firaCodeRegular.otf",
|
||||||
|
textMultiline = true,
|
||||||
|
backgroundAlpha = 0,
|
||||||
|
textColour = theme.foreground,
|
||||||
|
name = "output"
|
||||||
|
})
|
||||||
|
|
||||||
|
if not doNotHook then
|
||||||
|
teverse.debug:on("print", function(msg)
|
||||||
|
pcall(function()
|
||||||
|
text.text = string.sub(os.date("%H:%M:%S") .. " : " .. msg .. "\n" .. text.text, 0, 500)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return container, text
|
||||||
|
end
|
||||||
|
}
|
44
create.lua
44
create.lua
|
@ -1,44 +0,0 @@
|
||||||
--[[
|
|
||||||
create.lua
|
|
||||||
Copyright (c) 2020 teverse.com
|
|
||||||
|
|
||||||
This script is ran when the user loads create mode,
|
|
||||||
it is given workshop level sandboxing permissions.
|
|
||||||
|
|
||||||
However, scripts required from this script will not inherit workshop apis.
|
|
||||||
We overcome this by manually passing a reference to the workshop object to the required "main.lua" script.
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
-- SETTING UP A LOCAL DEVELOPMENT CREATE MODE --
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
1) Make sure you're looking at your local version
|
|
||||||
of this script and not the git version.
|
|
||||||
|
|
||||||
On Windows, this script can be found at "%localappdata%/teverse/create.lua"
|
|
||||||
|
|
||||||
2) Clone the Teverse Repo from Github anywhere on your PC e.g. your Desktop,
|
|
||||||
preferably away from the Teverse directory.
|
|
||||||
|
|
||||||
>> git clone https://github.com/teverse/teverse.git
|
|
||||||
|
|
||||||
3) Uncomment LINE 42 below,
|
|
||||||
making sure to include the FULL PATH to your newly cloned repo.
|
|
||||||
|
|
||||||
(!) You must include a following forward slash (!)
|
|
||||||
|
|
||||||
(!) Do not use backslashes (!)
|
|
||||||
|
|
||||||
VALID examples:
|
|
||||||
>> engine.workshop:setTevGit("C:/Users/YOURNAME/Desktop/teverse/")
|
|
||||||
>> engine.workshop:setTevGit("C:/teverse/")
|
|
||||||
>> engine.workshop:setTevGit("C:/Users/YOURNAME/Documents/teverse/")
|
|
||||||
|
|
||||||
(!) BAD examples:
|
|
||||||
(!) >> engine.workshop:setTevGit("C:/Users/YOURNAME/Desktop/teverse") -- missing slash on the end
|
|
||||||
(!) >> engine.workshop:setTevGit("C:\Users\YOURNAME\Desktop\teverse\") -- backslashes
|
|
||||||
]]
|
|
||||||
|
|
||||||
--engine.workshop:setTevGit('C:/Users/YOURNAME/Desktop/teverse/')
|
|
||||||
|
|
||||||
require("tevgit:workshop/main.lua")(engine.workshop)
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
$input v_worldPos, v_view, v_normal, v_tangent, v_bitangent, v_color0, v_color1
|
||||||
|
|
||||||
|
#include <teverse.sh>
|
||||||
|
#include <lighting.sh>
|
||||||
|
|
||||||
|
uniform vec4 u_lightRgbInnerR;
|
||||||
|
uniform vec4 u_camPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragColor = vec4(encodeNormalUint(v_normal), 0.0);
|
||||||
|
}
|
|
@ -0,0 +1,672 @@
|
||||||
|
#ifndef __LIGHTING_SH__
|
||||||
|
#define __LIGHTING_SH__
|
||||||
|
|
||||||
|
|
||||||
|
const float PI = 3.1415;
|
||||||
|
|
||||||
|
vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir)
|
||||||
|
{
|
||||||
|
float ndotl = dot(_normal, _lightDir);
|
||||||
|
vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal);
|
||||||
|
float rdotv = dot(reflected, _viewDir);
|
||||||
|
return vec2(ndotl, rdotv);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fresnel(float _ndotl, float _bias, float _pow)
|
||||||
|
{
|
||||||
|
float facing = (1.0 - _ndotl);
|
||||||
|
return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 lit(float _ndotl, float _rdotv, float _m)
|
||||||
|
{
|
||||||
|
float diff = max(0.0, _ndotl);
|
||||||
|
float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m);
|
||||||
|
return vec4(1.0, diff, spec, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 powRgba(vec4 _rgba, float _pow)
|
||||||
|
{
|
||||||
|
vec4 result;
|
||||||
|
result.xyz = pow(_rgba.xyz, vec3_splat(_pow) );
|
||||||
|
result.w = _rgba.w;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 calcLight(vec3 _wpos, vec3 _normal, vec3 _view, vec3 _lightPos, float _lightRadius, vec3 _lightRgb, float _lightInner)
|
||||||
|
{
|
||||||
|
vec3 lp = _lightPos - _wpos;
|
||||||
|
float attn = 1.0 - smoothstep(_lightInner, 1.0, length(lp) / _lightRadius);
|
||||||
|
vec3 lightDir = normalize(lp);
|
||||||
|
vec2 bln = blinn(lightDir, _normal, _view);
|
||||||
|
vec4 lc = lit(bln.x, bln.y, 1.0);
|
||||||
|
vec3 rgb = _lightRgb * saturate(lc.y) * attn;
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
float toClipSpaceDepth(float _depthTextureZ)
|
||||||
|
{
|
||||||
|
#if BGFX_SHADER_LANGUAGE_GLSL
|
||||||
|
return _depthTextureZ * 2.0 - 1.0;
|
||||||
|
#else
|
||||||
|
return _depthTextureZ;
|
||||||
|
#endif // BGFX_SHADER_LANGUAGE_GLSL
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos)
|
||||||
|
{
|
||||||
|
vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) );
|
||||||
|
return wpos.xyz / wpos.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness*roughness;
|
||||||
|
float a2 = a*a;
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
|
float num = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = PI * denom * denom;
|
||||||
|
|
||||||
|
return num / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r*r) / 8.0;
|
||||||
|
|
||||||
|
float num = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return num / denom;
|
||||||
|
}
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
|
{
|
||||||
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GBufferData
|
||||||
|
{
|
||||||
|
vec3 base_color;
|
||||||
|
float ambient_occlusion;
|
||||||
|
vec3 world_normal;
|
||||||
|
float roughness;
|
||||||
|
vec3 emissive_color;
|
||||||
|
float metalness;
|
||||||
|
vec3 subsurface_color;
|
||||||
|
float subsurface_opacity;
|
||||||
|
float depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
void encodeGBuffer(in GBufferData data, inout vec4 result[3])
|
||||||
|
{
|
||||||
|
result[0] = vec4(data.base_color, data.ambient_occlusion);
|
||||||
|
//result[1] = vec4(encodeNormalOctahedron(data.world_normal), 0.0f, data.roughness);
|
||||||
|
result[1] = vec4(encodeNormalUint(data.world_normal), data.roughness);
|
||||||
|
result[2] = vec4(data.emissive_color, data.metalness);
|
||||||
|
//result[3] = vec4(data.subsurface_color, data.subsurface_opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
GBufferData decodeGBuffer(vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex4)
|
||||||
|
{
|
||||||
|
GBufferData data;
|
||||||
|
|
||||||
|
vec4 data0 = texture2D(tex0, texcoord);
|
||||||
|
vec4 data1 = texture2D(tex1, texcoord);
|
||||||
|
vec4 data2 = texture2D(tex2, texcoord);
|
||||||
|
float deviceDepth = texture2D(tex4, texcoord).x;
|
||||||
|
|
||||||
|
data.base_color = data0.xyz;
|
||||||
|
data.ambient_occlusion = data0.w;
|
||||||
|
//data.world_normal = decodeNormalOctahedron(data1.xy);
|
||||||
|
data.world_normal = decodeNormalUint(data1.xyz);
|
||||||
|
data.roughness = data1.w;
|
||||||
|
data.emissive_color = data2.xyz;
|
||||||
|
data.metalness = data2.w;
|
||||||
|
data.subsurface_color = vec3(1.0, 1.0, 1.0);
|
||||||
|
data.subsurface_opacity = 1.0;
|
||||||
|
data.depth = toClipSpaceDepth(deviceDepth);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float BiasedNDotL(float NDotLWithoutSaturate )
|
||||||
|
{
|
||||||
|
return saturate(NDotLWithoutSaturate * 1.08f - 0.08f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Square( float x )
|
||||||
|
{
|
||||||
|
return x*x;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Square( vec2 x )
|
||||||
|
{
|
||||||
|
return x*x;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 Square( vec3 x )
|
||||||
|
{
|
||||||
|
return x*x;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 Square( vec4 x )
|
||||||
|
{
|
||||||
|
return x*x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Pow5( float x )
|
||||||
|
{
|
||||||
|
float xx = x*x;
|
||||||
|
return xx * xx * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Pow5( vec2 x )
|
||||||
|
{
|
||||||
|
vec2 xx = x*x;
|
||||||
|
return xx * xx * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 Pow5( vec3 x )
|
||||||
|
{
|
||||||
|
vec3 xx = x*x;
|
||||||
|
return xx * xx * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 Pow5( vec4 x )
|
||||||
|
{
|
||||||
|
vec4 xx = x*x;
|
||||||
|
return xx * xx * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float UnClampedPow(float X, float Y)
|
||||||
|
{
|
||||||
|
return pow(X, Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ClampedPow(float X,float Y)
|
||||||
|
{
|
||||||
|
return pow(max(abs(X),0.000001f),Y);
|
||||||
|
}
|
||||||
|
float PhongShadingPow(float X, float Y)
|
||||||
|
{
|
||||||
|
// The following clamping is done to prevent NaN being the result of the specular power computation.
|
||||||
|
// Clamping has a minor performance cost.
|
||||||
|
|
||||||
|
// In HLSL pow(a, b) is implemented as exp2(log2(a) * b).
|
||||||
|
|
||||||
|
// For a=0 this becomes exp2(-inf * 0) = exp2(NaN) = NaN.
|
||||||
|
|
||||||
|
// In order to avoid platform differences and rarely occuring image atrifacts we clamp the base.
|
||||||
|
|
||||||
|
// Note: Clamping the exponent seemed to fix the issue mentioned TTP but we decided to fix the root and accept the
|
||||||
|
// minor performance cost.
|
||||||
|
|
||||||
|
return ClampedPow(X, Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float RadialAttenuation(vec3 WorldLightVector, float FalloffExponent)
|
||||||
|
{
|
||||||
|
float NormalizeDistanceSquared = dot(WorldLightVector, WorldLightVector);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
return pow(1.0f - saturate(NormalizeDistanceSquared), FalloffExponent);
|
||||||
|
#else
|
||||||
|
// light less than x % is considered 0
|
||||||
|
const float CutoffPercentage = 30.0f;
|
||||||
|
|
||||||
|
float CutoffFraction = CutoffPercentage * 0.01f;
|
||||||
|
// those could be computed on C++ side
|
||||||
|
float PreCompX = 1.0f - CutoffFraction;
|
||||||
|
float PreCompY = CutoffFraction;
|
||||||
|
float PreCompZ = CutoffFraction / PreCompX;
|
||||||
|
return (1.0f / ( saturate(NormalizeDistanceSquared) * PreCompX + PreCompY) - 1.0f) * PreCompZ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates attenuation for a spot light.
|
||||||
|
* WorldLightVector is the vector from the position being shaded to the light, divided by the radius of the light.
|
||||||
|
* SpotDirection is the direction of the spot light.
|
||||||
|
* SpotAngles.x is CosOuterCone, SpotAngles.y is InvCosConeDifference.
|
||||||
|
*/
|
||||||
|
float SpotAttenuation(vec3 WorldLightVector, vec3 SpotDirection, vec2 SpotAngles)
|
||||||
|
{
|
||||||
|
float ConeAngleFalloff = Square(saturate((dot(normalize(WorldLightVector), -SpotDirection) - SpotAngles.x) * SpotAngles.y));
|
||||||
|
return ConeAngleFalloff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find representative incoming light direction and energy modification
|
||||||
|
vec3 AreaLightSpecular( float SourceRadius, float SourceLength, vec3 LightDirection, vec3 LobeRoughness, inout vec3 ToLight, inout vec3 L, vec3 V, vec3 N )
|
||||||
|
{
|
||||||
|
vec3 LobeEnergy = vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
vec3 m = LobeRoughness * LobeRoughness;
|
||||||
|
vec3 R = reflect( -V, N );
|
||||||
|
float InvDistToLight = 1.0f / ( dot( ToLight, ToLight ) );
|
||||||
|
|
||||||
|
if( SourceLength > 0.0f )
|
||||||
|
{
|
||||||
|
// Energy conservation
|
||||||
|
// asin(x) is angle to sphere, atan(x) is angle to disk, saturate(x) is free and in the middle
|
||||||
|
float LineAngle = saturate( SourceLength * InvDistToLight );
|
||||||
|
LobeEnergy *= m / saturate( m + 0.5f * LineAngle );
|
||||||
|
|
||||||
|
// Closest point on line segment to ray
|
||||||
|
vec3 L01 = LightDirection * SourceLength;
|
||||||
|
vec3 L0 = ToLight - 0.5f * L01;
|
||||||
|
vec3 L1 = ToLight + 0.5f * L01;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// Shortest distance
|
||||||
|
float a = Square( SourceLength );
|
||||||
|
float b = dot( R, L01 );
|
||||||
|
float t = saturate( dot( L0, b*R - L01 ) / (a - b*b) );
|
||||||
|
#else
|
||||||
|
// Smallest angle
|
||||||
|
float A = Square( SourceLength );
|
||||||
|
float B = 2.0f * dot( L0, L01 );
|
||||||
|
float C = dot( L0, L0 );
|
||||||
|
float D = dot( R, L0 );
|
||||||
|
float E = dot( R, L01 );
|
||||||
|
float t = saturate( (B*D - 2.0f*C*E) / (B*E - 2.0f*A*D) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ToLight = L0 + t * L01;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( SourceRadius > 0.0f )
|
||||||
|
{
|
||||||
|
// Energy conservation
|
||||||
|
// asin(x) is angle to sphere, atan(x) is angle to disk, saturate(x) is free and in the middle
|
||||||
|
float SphereAngle = saturate( SourceRadius * InvDistToLight );
|
||||||
|
LobeEnergy *= Square( m / saturate( m + 0.5f * SphereAngle ) );
|
||||||
|
|
||||||
|
// Closest point on sphere to ray
|
||||||
|
vec3 ClosestPointOnRay = dot( ToLight, R ) * R;
|
||||||
|
vec3 CenterToRay = ClosestPointOnRay - ToLight;
|
||||||
|
vec3 ClosestPointOnSphere = ToLight + CenterToRay * saturate( SourceRadius / sqrt( dot( CenterToRay, CenterToRay ) ) );
|
||||||
|
ToLight = ClosestPointOnSphere;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
L = normalize( ToLight );
|
||||||
|
|
||||||
|
return LobeEnergy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
BRDF: Bidirectional reflectance distribution functions.
|
||||||
|
=============================================================================*/
|
||||||
|
// Physically based shading model
|
||||||
|
// parameterized with the below options
|
||||||
|
|
||||||
|
// Diffuse model
|
||||||
|
// 0: Lambert
|
||||||
|
// 1: Burley
|
||||||
|
// 2: Oren-Nayar
|
||||||
|
#define PHYSICAL_DIFFUSE 0
|
||||||
|
|
||||||
|
// Microfacet distribution function
|
||||||
|
// 0: Blinn
|
||||||
|
// 1: Beckmann
|
||||||
|
// 2: GGX
|
||||||
|
#define PHYSICAL_SPEC_D 2
|
||||||
|
|
||||||
|
// Geometric attenuation or shadowing
|
||||||
|
// 0: Implicit
|
||||||
|
// 1: Neumann
|
||||||
|
// 2: Kelemen
|
||||||
|
// 3: Schlick
|
||||||
|
// 4: Smith (matched to GGX)
|
||||||
|
// 5: SmithJointApprox
|
||||||
|
// 6: CookTorrance
|
||||||
|
#define PHYSICAL_SPEC_V 4
|
||||||
|
|
||||||
|
// Fresnel
|
||||||
|
// 0: None
|
||||||
|
// 1: Schlick
|
||||||
|
// 2: CookTorrance
|
||||||
|
// 3: Fresnel
|
||||||
|
#define PHYSICAL_SPEC_F 1
|
||||||
|
|
||||||
|
#define PI 3.1415926535f
|
||||||
|
#define RECIP_PI 1.0f / PI
|
||||||
|
#define RADIANS_PER_DEGREE 0.0174532925f
|
||||||
|
#define DEGREES_PER_RADIAN 57.2957795f
|
||||||
|
/*=============================================================================
|
||||||
|
BRDF: Diffuse functions.
|
||||||
|
=============================================================================*/
|
||||||
|
vec3 Diffuse_Lambert( vec3 DiffuseColor )
|
||||||
|
{
|
||||||
|
return DiffuseColor * RECIP_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Burley 2012, "Physically-Based Shading at Disney"]
|
||||||
|
// [Lagrade et al. 2014, "Moving Frostbite to Physically Based Rendering"]
|
||||||
|
vec3 Diffuse_Burley( vec3 DiffuseColor, float Roughness, float NoV, float NoL, float VoH )
|
||||||
|
{
|
||||||
|
float FD90 = 0.5f + 2.0f * VoH * VoH * Roughness;
|
||||||
|
float FdV = 1.0f + (FD90 - 1.0f) * Pow5( 1.0f - NoV );
|
||||||
|
float FdL = 1.0f + (FD90 - 1.0f) * Pow5( 1.0f - NoL );
|
||||||
|
return DiffuseColor * ( (1.0f / PI) * FdV * FdL );
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Gotanda 2012, "Beyond a Simple Physically Based Blinn-Phong Model in Real-Time"]
|
||||||
|
vec3 Diffuse_OrenNayar( vec3 DiffuseColor, float Roughness, float NoV, float NoL, float VoH )
|
||||||
|
{
|
||||||
|
float a = Roughness * Roughness;
|
||||||
|
float s = a;// / ( 1.29 + 0.5 * a );
|
||||||
|
float s2 = s * s;
|
||||||
|
float VoL = 2.0f * VoH * VoH - 1.0f; // double angle identity
|
||||||
|
float Cosri = VoL - NoV * NoL;
|
||||||
|
float C1 = 1.0f - 0.5f * s2 / (s2 + 0.33f);
|
||||||
|
float C2 = 0.45f * s2 / (s2 + 0.09f) * Cosri * ( Cosri >= 0.0f ? rcp( max( NoL, NoV ) ) : 1.0f );
|
||||||
|
return DiffuseColor / PI * ( C1 + C2 ) * ( 1.0f + Roughness * 0.5f );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 Diffuse( vec3 DiffuseColor, float Roughness, float NoV, float NoL, float VoH )
|
||||||
|
{
|
||||||
|
#if PHYSICAL_DIFFUSE == 0
|
||||||
|
return Diffuse_Lambert( DiffuseColor );
|
||||||
|
#elif PHYSICAL_DIFFUSE == 1
|
||||||
|
return Diffuse_Burley( DiffuseColor, Roughness, NoV, NoL, VoH );
|
||||||
|
#elif PHYSICAL_DIFFUSE == 2
|
||||||
|
return Diffuse_OrenNayar( DiffuseColor, Roughness, NoV, NoL, VoH );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
BRDF: Distribution functions.
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
// [Blinn 1977, "Models of light reflection for computer synthesized pictures"]
|
||||||
|
float D_Blinn( float Roughness, float NoH )
|
||||||
|
{
|
||||||
|
float m = Roughness * Roughness;
|
||||||
|
float m2 = m * m;
|
||||||
|
float n = 2.0f / m2 - 2.0f;
|
||||||
|
return (n+2.0f) / (2.0f*PI) * PhongShadingPow( NoH, n ); // 1 mad, 1 exp, 1 mul, 1 log
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Beckmann 1963, "The scattering of electromagnetic waves from rough surfaces"]
|
||||||
|
float D_Beckmann( float Roughness, float NoH )
|
||||||
|
{
|
||||||
|
float m = Roughness * Roughness;
|
||||||
|
float m2 = m * m;
|
||||||
|
float NoH2 = NoH * NoH;
|
||||||
|
return exp( (NoH2 - 1.0f) / (m2 * NoH2) ) / ( PI * m2 * NoH2 * NoH2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// GGX / Trowbridge-Reitz
|
||||||
|
// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
|
||||||
|
float D_GGX( float Roughness, float NoH )
|
||||||
|
{
|
||||||
|
float m = Roughness * Roughness;
|
||||||
|
float m2 = m * m;
|
||||||
|
float d = ( NoH * m2 - NoH ) * NoH + 1.0f; // 2 mad
|
||||||
|
return m2 / ( PI*d*d ); // 4 mul, 1 rcp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anisotropic GGX
|
||||||
|
// [Burley 2012, "Physically-Based Shading at Disney"]
|
||||||
|
float D_GGXaniso( float RoughnessX, float RoughnessY, float NoH, vec3 H, vec3 X, vec3 Y )
|
||||||
|
{
|
||||||
|
float mx = RoughnessX * RoughnessX;
|
||||||
|
float my = RoughnessY * RoughnessY;
|
||||||
|
float XoH = dot( X, H );
|
||||||
|
float YoH = dot( Y, H );
|
||||||
|
float d = XoH*XoH / (mx*mx) + YoH*YoH / (my*my) + NoH*NoH;
|
||||||
|
return 1.0f / ( PI * mx*my * d*d );
|
||||||
|
}
|
||||||
|
|
||||||
|
float Distribution( float Roughness, float NoH )
|
||||||
|
{
|
||||||
|
#if PHYSICAL_SPEC_D == 0
|
||||||
|
return D_Blinn( Roughness, NoH );
|
||||||
|
#elif PHYSICAL_SPEC_D == 1
|
||||||
|
return D_Beckmann( Roughness, NoH );
|
||||||
|
#elif PHYSICAL_SPEC_D == 2
|
||||||
|
return D_GGX( Roughness, NoH );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
BRDF: Visibility functions.
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
float Vis_Implicit( )
|
||||||
|
{
|
||||||
|
return 0.25f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Neumann et al. 1999, "Compact metallic reflectance models"]
|
||||||
|
float Vis_Neumann( float NoV, float NoL )
|
||||||
|
{
|
||||||
|
return 1.0f / ( 4.0f * max( NoL, NoV ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Kelemen 2001, "A microfacet based coupled specular-matte brdf model with importance sampling"]
|
||||||
|
float Vis_Kelemen( float VoH )
|
||||||
|
{
|
||||||
|
return rcp( 4.0f * VoH * VoH );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tuned to match behavior of G_Smith
|
||||||
|
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
|
||||||
|
float Vis_Schlick( float Roughness, float NoV, float NoL )
|
||||||
|
{
|
||||||
|
float k = Square( Roughness ) * 0.5f;
|
||||||
|
float Vis_SchlickV = NoV * (1.0f - k) + k;
|
||||||
|
float Vis_SchlickL = NoL * (1.0f - k) + k;
|
||||||
|
return 0.25f / ( Vis_SchlickV * Vis_SchlickL );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smith term for GGX modified by Disney to be less "hot" for small roughness values
|
||||||
|
// [Smith 1967, "Geometrical shadowing of a random rough surface"]
|
||||||
|
// [Burley 2012, "Physically-Based Shading at Disney"]
|
||||||
|
float Vis_Smith( float Roughness, float NoV, float NoL )
|
||||||
|
{
|
||||||
|
float a = Square( Roughness );
|
||||||
|
float a2 = a*a;
|
||||||
|
|
||||||
|
float Vis_SmithV = NoV + sqrt( NoV * (NoV - NoV * a2) + a2 );
|
||||||
|
float Vis_SmithL = NoL + sqrt( NoL * (NoL - NoL * a2) + a2 );
|
||||||
|
return rcp( Vis_SmithV * Vis_SmithL );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appoximation of joint Smith term for GGX
|
||||||
|
// [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"]
|
||||||
|
float Vis_SmithJointApprox( float Roughness, float NoV, float NoL )
|
||||||
|
{
|
||||||
|
float a = Square( Roughness );
|
||||||
|
float Vis_SmithV = NoL * ( NoV * ( 1.0f - a ) + a );
|
||||||
|
float Vis_SmithL = NoV * ( NoL * ( 1.0f - a ) + a );
|
||||||
|
return 0.5f * rcp( Vis_SmithV + Vis_SmithL );
|
||||||
|
}
|
||||||
|
|
||||||
|
float Vis_CookTorrance(float Roughness, float NoV, float NoL, float VoH, float NoH )
|
||||||
|
{
|
||||||
|
float a = Square( Roughness );
|
||||||
|
return min(1.0f, min((2.0f * NoH * NoV)/VoH, (2.0f * NoH * NoL)/ VoH));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vis = G / (4*NoL*NoV)
|
||||||
|
float Visibility( float Roughness, float NoV, float NoL, float VoH, float NoH )
|
||||||
|
{
|
||||||
|
#if PHYSICAL_SPEC_V == 0
|
||||||
|
return Vis_Implicit( );
|
||||||
|
#elif PHYSICAL_SPEC_V == 1
|
||||||
|
return Vis_Neumann( NoV, NoL );
|
||||||
|
#elif PHYSICAL_SPEC_V == 2
|
||||||
|
return Vis_Kelemen( VoH );
|
||||||
|
#elif PHYSICAL_SPEC_V == 3
|
||||||
|
return Vis_Schlick( Roughness, NoV, NoL );
|
||||||
|
#elif PHYSICAL_SPEC_V == 4
|
||||||
|
return Vis_Smith( Roughness, NoV, NoL );
|
||||||
|
#elif PHYSICAL_SPEC_V == 5
|
||||||
|
return Vis_SmithJointApprox( Roughness, NoV, NoL );
|
||||||
|
#elif PHYSICAL_SPEC_V == 6
|
||||||
|
return Vis_CookTorrance( Roughness, NoV, NoL, VoH, NoH );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
BRDF: Fresnel functions.
|
||||||
|
=============================================================================*/
|
||||||
|
vec3 F_None( vec3 SpecularColor )
|
||||||
|
{
|
||||||
|
return SpecularColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
|
||||||
|
// [Lagarde 2012, "Spherical Gaussian approximation for Blinn-Phong, Phong and Fresnel"]
|
||||||
|
vec3 F_Schlick( vec3 SpecularColor, float VoH )
|
||||||
|
{
|
||||||
|
float Fc = Pow5( 1.0f - VoH ); // 1 sub, 3 mul
|
||||||
|
//return Fc + (1.0f - Fc) * SpecularColor; // 1 add, 3 mad
|
||||||
|
|
||||||
|
// Anything less than 2% is physically impossible and is instead considered to be shadowing
|
||||||
|
return saturate( 50.0f * SpecularColor.g ) * Fc + (1.0f - Fc) * SpecularColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 Fresnel_CookTorrance( vec3 SpecularColor, float VoH )
|
||||||
|
{
|
||||||
|
vec3 VdotH = vec3(VoH, VoH, VoH);
|
||||||
|
vec3 n = (1.0f + sqrt(SpecularColor)) / (1.0f - sqrt(SpecularColor));
|
||||||
|
vec3 g = sqrt(n * n + VdotH * VdotH - 1.0f);
|
||||||
|
|
||||||
|
vec3 part1 = (g - VdotH)/(g + VdotH);
|
||||||
|
vec3 part2 = ((g + VdotH) * VdotH - 1.0f)/((g - VdotH) * VdotH + 1.0f);
|
||||||
|
|
||||||
|
return max(vec3(0.0f, 0.0f, 0.0f), 0.5f * part1 * part1 * ( 1.0f + part2 * part2));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 F_Fresnel( vec3 SpecularColor, float VoH )
|
||||||
|
{
|
||||||
|
|
||||||
|
vec3 SpecularColorSqrt = sqrt( clamp( vec3(0.0f, 0.0f, 0.0f), vec3(0.99f, 0.99f, 0.99f), SpecularColor ) );
|
||||||
|
vec3 n = ( 1.0f + SpecularColorSqrt ) / ( 1.0f - SpecularColorSqrt );
|
||||||
|
vec3 g = sqrt( n*n + VoH*VoH - 1.0f );
|
||||||
|
return 0.5f * Square( (g - VoH) / (g + VoH) ) * ( 1.0f + Square( ((g+VoH)*VoH - 1.0f) / ((g-VoH)*VoH + 1.0f) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
vec3 F_Roughness(vec3 SpecularColor, float Roughness, float VoH)
|
||||||
|
{
|
||||||
|
// Sclick using roughness to attenuate fresnel.
|
||||||
|
return (SpecularColor + (max(vec3(1.0f-Roughness, 1.0f-Roughness, 1.0f-Roughness), SpecularColor) - SpecularColor) * pow((1.0f - VoH), 5.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 Fresnel( vec3 SpecularColor, float VoH )
|
||||||
|
{
|
||||||
|
#if PHYSICAL_SPEC_F == 0
|
||||||
|
return F_None( SpecularColor );
|
||||||
|
#elif PHYSICAL_SPEC_F == 1
|
||||||
|
return F_Schlick( SpecularColor, VoH );
|
||||||
|
#elif PHYSICAL_SPEC_F == 2
|
||||||
|
return Fresnel_CookTorrance( SpecularColor, VoH );
|
||||||
|
#elif PHYSICAL_SPEC_F == 3
|
||||||
|
return F_Fresnel( SpecularColor, VoH );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SurfaceShading
|
||||||
|
{
|
||||||
|
vec3 direct;
|
||||||
|
vec3 indirect;
|
||||||
|
};
|
||||||
|
|
||||||
|
SurfaceShading StandardShading( vec3 DiffuseColor, vec3 IndirectDiffuse, vec3 SpecularColor, vec3 IndirectSpecular, vec3 LobeRoughness, vec3 LobeEnergy, float metalness, float occlusion, vec3 L, vec3 V, vec3 N )
|
||||||
|
{
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
float NoL = saturate( dot(N, L) );
|
||||||
|
float NoV = saturate( abs( dot(N, V) ) + 1e-5 );
|
||||||
|
float NoH = saturate( dot(N, H) );
|
||||||
|
float VoH = saturate( dot(V, H) );
|
||||||
|
float roughness = LobeRoughness[1];
|
||||||
|
// Generalized microfacet specular
|
||||||
|
float D = Distribution( roughness, NoH ) * LobeEnergy[1];
|
||||||
|
float Vis = Visibility( roughness, NoV, NoL, VoH, NoH );
|
||||||
|
vec3 F = Fresnel( SpecularColor, VoH );
|
||||||
|
|
||||||
|
vec3 diffuse_color = Diffuse( DiffuseColor, roughness, NoV, NoL, VoH );
|
||||||
|
|
||||||
|
float specular_occlusion = saturate( Square( NoV + occlusion ) - 1.0f + occlusion );
|
||||||
|
vec3 env_fresnel = F_Roughness(SpecularColor, roughness, NoV);
|
||||||
|
vec2 env_brdf = vec2(0.0, 0.0); //texture2D(BRDFIntegrationMap, vec2(NoV, roughness)).xy;
|
||||||
|
//set to 0 otherwise we get artefacts
|
||||||
|
env_brdf.y = 0.0f;
|
||||||
|
vec3 indirect_spec = IndirectSpecular * (env_fresnel * env_brdf.x + env_brdf.y) * specular_occlusion;
|
||||||
|
|
||||||
|
SurfaceShading shading;
|
||||||
|
shading.indirect = DiffuseColor * IndirectDiffuse + indirect_spec;
|
||||||
|
shading.direct = diffuse_color * LobeEnergy[2] + (D * Vis) * F;
|
||||||
|
return shading;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 SubsurfaceShading( vec3 SubsurfaceColor, float Opacity, float AO, vec3 L, vec3 V, vec3 N )
|
||||||
|
{
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
// to get an effect when you see through the material
|
||||||
|
// hard coded pow constant
|
||||||
|
float InScatter = pow(saturate(dot(L, -V)), 12.0f) * mix(3.0f, 0.1f, Opacity);
|
||||||
|
// wrap around lighting, /(PI*2) to be energy consistent (hack do get some view dependnt and light dependent effect)
|
||||||
|
// Opacity of 0 gives no normal dependent lighting, Opacity of 1 gives strong normal contribution
|
||||||
|
float NormalContribution = saturate(dot(N, H) * Opacity + 1.0f - Opacity);
|
||||||
|
float BackScatter = AO * NormalContribution / (PI * 2.0f);
|
||||||
|
|
||||||
|
// lerp to never exceed 1 (energy conserving)
|
||||||
|
return SubsurfaceColor * mix(BackScatter, 1.0f, InScatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 SubsurfaceShadingTwoSided( vec3 SubsurfaceColor, vec3 L, vec3 V, vec3 N )
|
||||||
|
{
|
||||||
|
// http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
|
||||||
|
float Wrap = 0.5f;
|
||||||
|
float NoL = saturate( ( dot(-N, L) + Wrap ) / Square( 1.0f + Wrap ) );
|
||||||
|
|
||||||
|
// GGX scatter distribution
|
||||||
|
float VoL = saturate( dot(V, -L) );
|
||||||
|
float a = 0.6f;
|
||||||
|
float a2 = a * a;
|
||||||
|
float d = ( VoL * a2 - VoL ) * VoL + 1.0f; // 2 mad
|
||||||
|
float GGX = (a2 / PI) / (d * d); // 2 mul, 1 rcp
|
||||||
|
return NoL * GGX * SubsurfaceColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ComputeReflectionCaptureMipFromRoughness(float Roughness, float maxMipLevels)
|
||||||
|
{
|
||||||
|
const float REFLECTION_CAPTURE_ROUGHEST_MIP = 1.0f;
|
||||||
|
const float REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE = 1.5f;
|
||||||
|
// Heuristic that maps roughness to mip level
|
||||||
|
// This is done in a way such that a certain mip level will always have the same roughness, regardless of how many mips are in the texture
|
||||||
|
// Using more mips in the cubemap just allows sharper reflections to be supported
|
||||||
|
// Note: this must match the logic in FilterReflectionEnvironment that generates the mip filter samples!
|
||||||
|
float LevelFrom1x1 = REFLECTION_CAPTURE_ROUGHEST_MIP - REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE * log2(Roughness);
|
||||||
|
//// Note: must match GReflectionCaptureSize
|
||||||
|
float HardcodedNumCaptureArrayMips = maxMipLevels;
|
||||||
|
return HardcodedNumCaptureArrayMips - 1.0f - LevelFrom1x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __LIGHTING_SH__
|
|
@ -0,0 +1,24 @@
|
||||||
|
vec3 v_worldPos : TEXCOORD1 = vec3(0.0, 0.0, 0.0);
|
||||||
|
vec3 v_view : TEXCOORD2 = vec3(0.0, 0.0, 0.0);
|
||||||
|
vec3 v_position : TEXCOORD3 = vec3(0.0, 0.0, 0.0);
|
||||||
|
vec3 v_normal : NORMAL = vec3(0.0, 0.0, 1.0);
|
||||||
|
vec3 v_tangent : TANGENT = vec3(1.0, 0.0, 0.0);
|
||||||
|
vec3 v_bitangent : BINORMAL = vec3(0.0, 1.0, 0.0);
|
||||||
|
vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
vec4 v_color1 : COLOR1 = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
|
||||||
|
|
||||||
|
vec3 a_position : POSITION;
|
||||||
|
vec4 a_normal : NORMAL;
|
||||||
|
vec4 a_tangent : TANGENT;
|
||||||
|
vec2 a_texcoord0 : TEXCOORD0;
|
||||||
|
vec4 a_color0 : COLOR0;
|
||||||
|
vec4 i_data0 : TEXCOORD7;
|
||||||
|
vec4 i_data1 : TEXCOORD6;
|
||||||
|
vec4 i_data2 : TEXCOORD5;
|
||||||
|
vec4 i_data3 : TEXCOORD4;
|
||||||
|
vec4 i_data4 : TEXCOORD3;
|
||||||
|
vec4 a_texcoord2 : TEXCOORD2;
|
||||||
|
|
||||||
|
ivec4 a_indices : BLENDINDICES;
|
||||||
|
vec4 a_weight : BLENDWEIGHT;
|
|
@ -0,0 +1,47 @@
|
||||||
|
$input a_position, a_normal, a_tangent, a_color0, i_data0, i_data1, i_data2, i_data3, i_data4, a_texcoord2
|
||||||
|
$output v_worldPos, v_view, v_normal, v_tangent, v_bitangent, v_color0, v_color1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portions of this file may have been directly taken or adapted from the following open sourced projects:
|
||||||
|
*
|
||||||
|
* Copyright 2011-2019 Branimir Karadzic. All rights reserved.
|
||||||
|
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <teverse.sh>
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
mat4 model;
|
||||||
|
model[0] = i_data0;
|
||||||
|
model[1] = i_data1;
|
||||||
|
model[2] = i_data2;
|
||||||
|
model[3] = i_data3;
|
||||||
|
|
||||||
|
vec3 wpos = instMul(model, vec4(a_position, 1.0) ).xyz;
|
||||||
|
gl_Position = mul(u_viewProj, vec4(wpos, 1.0) );
|
||||||
|
v_worldPos = wpos;
|
||||||
|
|
||||||
|
mat3 modelIT = calculateInverseTranspose(u_model[0]);
|
||||||
|
|
||||||
|
vec4 normal = a_normal * 2.0 - 1.0;
|
||||||
|
vec4 tangent = a_tangent * 2.0 - 1.0;
|
||||||
|
|
||||||
|
vec3 wnormal = normalize(mul(modelIT, normal.xyz ));
|
||||||
|
wnormal = instMul(model, vec4(wnormal, 1.0) ).xyz;
|
||||||
|
|
||||||
|
vec3 wtangent = normalize(mul(modelIT, tangent.xyz ));
|
||||||
|
|
||||||
|
vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz;
|
||||||
|
v_view = view; //mul(view, tbn);
|
||||||
|
|
||||||
|
v_normal = normalize(wnormal);
|
||||||
|
v_tangent = wtangent;
|
||||||
|
v_bitangent = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
//v_position = a_position;
|
||||||
|
|
||||||
|
v_color0 = i_data4;
|
||||||
|
v_color1 = a_texcoord2;
|
||||||
|
}
|
282
tevEd/main.lua
282
tevEd/main.lua
|
@ -1,282 +0,0 @@
|
||||||
--local module = {}
|
|
||||||
local tevEd = require("tevgit:tevEd/tevEd.lua")
|
|
||||||
|
|
||||||
tevEd.addTutorial("Introduction", "Getting Started", "tevEd/tutorials/intro.lua")
|
|
||||||
--[[
|
|
||||||
tevEd.addTutorial("Introduction", "Introducing Blocks", "tevEd/tutorials/intro.lua")
|
|
||||||
tevEd.addTutorial("Introduction", "Introducing GUIs", "tevEd/tutorials/intro.lua")
|
|
||||||
|
|
||||||
tevEd.addTutorial("3D", "Using Meshes", "tevEd/tutorials/intro.lua")
|
|
||||||
tevEd.addTutorial("3D", "Physics Forces", "tevEd/tutorials/intro.lua")
|
|
||||||
tevEd.addTutorial("3D", "Making an Interactive Scene", "tevEd/tutorials/intro.lua")
|
|
||||||
|
|
||||||
tevEd.addTutorial("Interfaces", "Fun with Frames", "tevEd/tutorials/intro.lua")
|
|
||||||
tevEd.addTutorial("Interfaces", "Introducing Images", "tevEd/tutorials/intro.lua")
|
|
||||||
--]]
|
|
||||||
|
|
||||||
local mainContainer = nil
|
|
||||||
local workshop = nil
|
|
||||||
|
|
||||||
local function runTutorial(module)
|
|
||||||
mainContainer:destroyChildren()
|
|
||||||
local tutorial = require("tevgit:"..module)
|
|
||||||
|
|
||||||
local tutorialContainer = engine.construct("guiFrame", mainContainer, {
|
|
||||||
size = guiCoord(1, 0, 1, -20),
|
|
||||||
backgroundAlpha = 0.1,
|
|
||||||
backgroundColour=colour:black(),
|
|
||||||
})
|
|
||||||
|
|
||||||
local header = engine.construct("guiFrame", mainContainer, {
|
|
||||||
size = guiCoord(1, 0, 0, 50),
|
|
||||||
backgroundAlpha = 0.1,
|
|
||||||
backgroundColour=colour:white(),
|
|
||||||
})
|
|
||||||
|
|
||||||
local title = engine.construct("guiTextBox", header, {
|
|
||||||
size = guiCoord(1,-20,1,0),
|
|
||||||
position = guiCoord(0,10,0,0),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
align = enums.align.middleLeft,
|
|
||||||
fontFile = "local:OpenSans-SemiBold.ttf",
|
|
||||||
fontSize = 24,
|
|
||||||
text = tutorial.name
|
|
||||||
})
|
|
||||||
|
|
||||||
engine.construct("guiTextBox", header, {
|
|
||||||
size = guiCoord(1,-(title.textDimensions.x + 30),1,0),
|
|
||||||
position = guiCoord(0,(title.textDimensions.x + 20),0,0),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
align = enums.align.middleLeft,
|
|
||||||
fontFile = "local:OpenSans-Regular.ttf",
|
|
||||||
fontSize = 18,
|
|
||||||
textAlpha = 0.5,
|
|
||||||
text = tutorial.description
|
|
||||||
})
|
|
||||||
|
|
||||||
local body = engine.construct("guiFrame", tutorialContainer, {
|
|
||||||
size = guiCoord(1, 0, 1, -50),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
position = guiCoord(0,0,0,50)
|
|
||||||
})
|
|
||||||
|
|
||||||
local instructions = engine.construct("guiFrame", body, {
|
|
||||||
size = guiCoord(1/4, 0, 1, 0),
|
|
||||||
backgroundColour=colour:fromRGB(37, 37, 44),
|
|
||||||
})
|
|
||||||
|
|
||||||
local code = engine.construct("guiFrame", body, {
|
|
||||||
size = guiCoord(1/2, 0, 1, 0),
|
|
||||||
position = guiCoord(1/4, 0, 0, 0),
|
|
||||||
backgroundColour= colour:fromRGB(40,42,54),
|
|
||||||
})
|
|
||||||
|
|
||||||
local codeTxt = engine.construct("guiTextBox", code, {
|
|
||||||
size = guiCoord(1, -20, 1, -14),
|
|
||||||
position = guiCoord(0, 10, 0, 7),
|
|
||||||
align = enums.align.topLeft,
|
|
||||||
fontFile = "tevurl:font/FiraCode-Regular.otf",
|
|
||||||
fontSize = 20,
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
multiline = true,
|
|
||||||
readOnly = true,
|
|
||||||
wrap = true,
|
|
||||||
text = ""
|
|
||||||
})
|
|
||||||
|
|
||||||
for _,page in pairs(tutorial.tutorial) do
|
|
||||||
instructions:destroyChildren()
|
|
||||||
if type(page) == "string" then
|
|
||||||
local txt = engine.construct("guiTextBox", instructions, {
|
|
||||||
size = guiCoord(1,-10,1,-10),
|
|
||||||
position = guiCoord(0,5,0,5),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
align = enums.align.topLeft,
|
|
||||||
textWrap = true,
|
|
||||||
fontFile = "local:OpenSans-Regular.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
text = page,
|
|
||||||
textColour = colour:white(),
|
|
||||||
handleEvents = false
|
|
||||||
})
|
|
||||||
|
|
||||||
local yield = true
|
|
||||||
local btn = engine.construct("guiTextBox", instructions, {
|
|
||||||
size = guiCoord(0, 120, 0, 24),
|
|
||||||
position = guiCoord(0,5,0,txt.textDimensions.y + 15),
|
|
||||||
align = enums.align.middle,
|
|
||||||
fontFile = "local:OpenSans-Regular.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
text = "Next",
|
|
||||||
backgroundColour= colour(0.4, 0.4, 0.4),
|
|
||||||
borderRadius = 4
|
|
||||||
})
|
|
||||||
|
|
||||||
btn:once("mouseLeftReleased", function ()
|
|
||||||
yield = false
|
|
||||||
end)
|
|
||||||
|
|
||||||
repeat wait() until not yield
|
|
||||||
|
|
||||||
btn:destroy()
|
|
||||||
elseif type(page) == "table" then
|
|
||||||
local y = 5
|
|
||||||
for _,v in pairs(page) do
|
|
||||||
if type(v) == "string" then
|
|
||||||
local txt = engine.construct("guiTextBox", instructions, {
|
|
||||||
size = guiCoord(1,-10,1,-10),
|
|
||||||
position = guiCoord(0,5,0,y),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
align = enums.align.topLeft,
|
|
||||||
wrap = true,
|
|
||||||
fontFile = "local:OpenSans-Regular.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
text = v,
|
|
||||||
textColour = colour:white(),
|
|
||||||
handleEvents = false
|
|
||||||
})
|
|
||||||
|
|
||||||
y = y + txt.textDimensions.y + 15
|
|
||||||
|
|
||||||
local yield = true
|
|
||||||
local btn = engine.construct("guiTextBox", instructions, {
|
|
||||||
size = guiCoord(0, 120, 0, 22),
|
|
||||||
position = guiCoord(0,5,0,y),
|
|
||||||
align = enums.align.middle,
|
|
||||||
fontFile = "local:OpenSans-Regular.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
text = "Continue",
|
|
||||||
backgroundColour= colour(0.4, 0.4, 0.4),
|
|
||||||
borderRadius = 4
|
|
||||||
})
|
|
||||||
|
|
||||||
btn:once("mouseLeftReleased", function ()
|
|
||||||
yield = false
|
|
||||||
end)
|
|
||||||
|
|
||||||
repeat wait() until not yield
|
|
||||||
|
|
||||||
btn:destroy()
|
|
||||||
elseif type(v) == "table" then
|
|
||||||
if v.type == "script" then
|
|
||||||
codeTxt.text = v.script
|
|
||||||
|
|
||||||
local btn = engine.construct("guiTextBox", instructions, {
|
|
||||||
size = guiCoord(0, 120, 0, 22),
|
|
||||||
position = guiCoord(0,5,0,y),
|
|
||||||
align = enums.align.middle,
|
|
||||||
fontFile = "local:OpenSans-Regular.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
text = v.btnText,
|
|
||||||
backgroundColour= colour(0.4, 0.4, 0.4),
|
|
||||||
borderRadius = 4
|
|
||||||
})
|
|
||||||
|
|
||||||
btn:once("mouseLeftReleased", function ()
|
|
||||||
v.action(workshop, codeTxt.text)
|
|
||||||
btn:destroy()
|
|
||||||
end)
|
|
||||||
|
|
||||||
elseif v.type == "helpText" then
|
|
||||||
local txt = engine.construct("guiTextBox", instructions, {
|
|
||||||
size = guiCoord(1,-10,1,-10),
|
|
||||||
position = guiCoord(0,5,0,y),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
align = enums.align.topLeft,
|
|
||||||
wrap = true,
|
|
||||||
fontFile = "tevurl:font/OpenSans-Italic.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
text = v.text,
|
|
||||||
textColour = colour:white(),
|
|
||||||
handleEvents = false
|
|
||||||
})
|
|
||||||
|
|
||||||
y = y + txt.textDimensions.y + 15
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function createMainInterface()
|
|
||||||
mainContainer:destroyChildren()
|
|
||||||
local sectionYPos = 0
|
|
||||||
for section, tutorials in pairs(tevEd.tutorials) do
|
|
||||||
|
|
||||||
local sectionContainer = engine.construct("guiFrame", mainContainer, {
|
|
||||||
position = guiCoord(0, 0, 0, sectionYPos),
|
|
||||||
backgroundAlpha = 0.1,
|
|
||||||
borderRadius = 4
|
|
||||||
})
|
|
||||||
|
|
||||||
engine.construct("guiTextBox", sectionContainer, {
|
|
||||||
size = guiCoord(1,-20,0,24),
|
|
||||||
position = guiCoord(0,10,0,10),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
align = enums.align.middleLeft,
|
|
||||||
fontFile = "local:OpenSans-SemiBold.ttf",
|
|
||||||
fontSize = 24,
|
|
||||||
text = section
|
|
||||||
})
|
|
||||||
|
|
||||||
local yPos = 44
|
|
||||||
|
|
||||||
for i,tutorial in pairs(tutorials) do
|
|
||||||
local tutorialContainer = engine.construct("guiFrame", sectionContainer, {
|
|
||||||
size = guiCoord(1, -20, 0, 30),
|
|
||||||
position = guiCoord(0, 10, 0, yPos),
|
|
||||||
backgroundColour = colour:black(),
|
|
||||||
backgroundAlpha = 0.1,
|
|
||||||
hoverCursor = "fa:s-hand-pointer"
|
|
||||||
})
|
|
||||||
|
|
||||||
tutorialContainer:mouseLeftReleased(function ()
|
|
||||||
runTutorial(tutorial[2])
|
|
||||||
end)
|
|
||||||
|
|
||||||
tutorialContainer:mouseFocused(function ()
|
|
||||||
tutorialContainer.backgroundAlpha = 0.2
|
|
||||||
end)
|
|
||||||
|
|
||||||
tutorialContainer:mouseUnfocused(function ()
|
|
||||||
tutorialContainer.backgroundAlpha = 0.1
|
|
||||||
end)
|
|
||||||
|
|
||||||
engine.construct("guiTextBox", tutorialContainer, {
|
|
||||||
size = guiCoord(0, 30,0,30),
|
|
||||||
position = guiCoord(0,0,0,0),
|
|
||||||
backgroundAlpha = 0.1,
|
|
||||||
textAlpha = 0.5,
|
|
||||||
align = enums.align.middle,
|
|
||||||
fontFile = "local:OpenSans-SemiBold.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
backgroundColour= colour:black(),
|
|
||||||
text = tostring(i),
|
|
||||||
handleEvents = false,
|
|
||||||
})
|
|
||||||
|
|
||||||
engine.construct("guiTextBox", tutorialContainer, {
|
|
||||||
size = guiCoord(1,-45,0,20),
|
|
||||||
position = guiCoord(0,40,0,5),
|
|
||||||
backgroundAlpha = 0,
|
|
||||||
align = enums.align.middleLeft,
|
|
||||||
fontFile = "local:OpenSans-Regular.ttf",
|
|
||||||
fontSize = 20,
|
|
||||||
text = tutorial[1],
|
|
||||||
handleEvents = false,
|
|
||||||
})
|
|
||||||
|
|
||||||
yPos = yPos + 40
|
|
||||||
end
|
|
||||||
|
|
||||||
sectionContainer.size = guiCoord(0, 240, 0, yPos)
|
|
||||||
sectionYPos = sectionYPos + yPos + 10
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return function(c, w)
|
|
||||||
mainContainer = c
|
|
||||||
workshop = w
|
|
||||||
createMainInterface()
|
|
||||||
end
|
|
|
@ -1,13 +0,0 @@
|
||||||
local tevEd = {}
|
|
||||||
|
|
||||||
tevEd.tutorials = {}
|
|
||||||
|
|
||||||
tevEd.addTutorial = function( section, name, module )
|
|
||||||
if not tevEd.tutorials[section] then
|
|
||||||
tevEd.tutorials[section] = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(tevEd.tutorials[section], {name, module})
|
|
||||||
end
|
|
||||||
|
|
||||||
return tevEd
|
|
|
@ -1,12 +0,0 @@
|
||||||
return {
|
|
||||||
runAndContinue = function (workshop, code)
|
|
||||||
workshop:loadString(code)
|
|
||||||
return true -- continue
|
|
||||||
end,
|
|
||||||
code = function(code, action)
|
|
||||||
return { type = "script", script = code, btnText = "Run", action = action }
|
|
||||||
end,
|
|
||||||
helpText = function(text)
|
|
||||||
return { type = "helpText", text = text }
|
|
||||||
end
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
local helpers = require("tevgit:tevEd/tutorials/helpers.lua")
|
|
||||||
|
|
||||||
return {
|
|
||||||
name = "Introduction",
|
|
||||||
description = "This tutorial will introduce the very basics of coding in a 3D sandbox with Lua.",
|
|
||||||
difficulty = 1,
|
|
||||||
|
|
||||||
tutorial = {
|
|
||||||
"Example Tutorial, This isn’t a real tutorial!",
|
|
||||||
{"This string is shown to the user", "This message is shown on the sampe page when the user hits next."},
|
|
||||||
{
|
|
||||||
"Teverse uses Lua, lets test some sample code before getting started...",
|
|
||||||
helpers.helpText("Press run to test this code."),
|
|
||||||
-- helpers.runAndContinue is a function that processes the user’s
|
|
||||||
-- input when they hit ‘run’. Any function can be used however,
|
|
||||||
-- helpers.runAndContinue is a quick way to simply execute the input w/o validation.
|
|
||||||
helpers.code("print(\"Hello Teverse!\")", helpers.runAndContinue),
|
|
||||||
},
|
|
||||||
"Congratulations, check the output on the right to see your creation!"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
-- Copyright 2020- Teverse
|
||||||
|
-- This script constructs (or builds) the modal views
|
||||||
|
|
||||||
|
local globals = require("tevgit:workshop/library/globals.lua") -- globals; variables or instances that can be shared between files
|
||||||
|
|
||||||
|
return {
|
||||||
|
construct = function(size, pos)
|
||||||
|
local data = {}
|
||||||
|
self = data
|
||||||
|
|
||||||
|
local container = teverse.construct("guiFrame", {
|
||||||
|
parent = teverse.interface,
|
||||||
|
name = "_container",
|
||||||
|
size = size,
|
||||||
|
position = pos,
|
||||||
|
backgroundColour = globals.defaultColours.white,
|
||||||
|
strokeColour = globals.defaultColours.white,
|
||||||
|
strokeRadius = 5,
|
||||||
|
strokeWidth = 1,
|
||||||
|
dropShadowAlpha = 0.4,
|
||||||
|
dropShadowBlur = 2,
|
||||||
|
dropShadowColour = colour.rgb(127, 127, 127),
|
||||||
|
dropShadowOffset = vector2(0.5, 1),
|
||||||
|
zIndex = 100
|
||||||
|
})
|
||||||
|
container.visible = false
|
||||||
|
|
||||||
|
self.content = container
|
||||||
|
self.display = function() container.visible = true end -- Display modal method
|
||||||
|
self.hide = function() container.visible = false end -- Hide modal method
|
||||||
|
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
}
|
|
@ -53,10 +53,10 @@ return {
|
||||||
size = guiCoord(0.95, 0, 0.4, 0),
|
size = guiCoord(0.95, 0, 0.4, 0),
|
||||||
position = guiCoord(0.025, 0, 0.23, 0),
|
position = guiCoord(0.025, 0, 0.23, 0),
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
borderAlpha = 1,
|
strokeAlpha = 1,
|
||||||
borderRadius = 5,
|
strokeRadius = 5,
|
||||||
borderWidth = 3,
|
strokeWidth = 3,
|
||||||
borderColour = globals.defaultColours.secondary
|
strokeColour = globals.defaultColours.secondary
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.construct("guiIcon", {
|
teverse.construct("guiIcon", {
|
||||||
|
@ -74,7 +74,7 @@ return {
|
||||||
size = guiCoord(0.82, 0, 1, 0),
|
size = guiCoord(0.82, 0, 1, 0),
|
||||||
position = guiCoord(0.15, 0, 0, 0),
|
position = guiCoord(0.15, 0, 0, 0),
|
||||||
text = text,
|
text = text,
|
||||||
fontSize = 16,
|
textSize = 16,
|
||||||
textColour = globals.defaultColours.primary,
|
textColour = globals.defaultColours.primary,
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
textAlign = enums.align.middle,
|
textAlign = enums.align.middle,
|
||||||
|
@ -111,17 +111,17 @@ return {
|
||||||
size = guiCoord(0.8, 0, 0.9, 0),
|
size = guiCoord(0.8, 0, 0.9, 0),
|
||||||
position = guiCoord(0.133, 0, 0.05, 0),
|
position = guiCoord(0.133, 0, 0.05, 0),
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
borderAlpha = 1,
|
strokeAlpha = 1,
|
||||||
borderRadius = 5,
|
strokeRadius = 5,
|
||||||
borderWidth = 3,
|
strokeWidth = 3,
|
||||||
borderColour = globals.defaultColours.primary
|
strokeColour = globals.defaultColours.primary
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.construct("guiIcon", {
|
teverse.construct("guiIcon", {
|
||||||
parent = bodyContainer,
|
parent = bodyContainer,
|
||||||
size = guiCoord(0, 16, 0, 16),
|
size = guiCoord(0, 16, 0, 16),
|
||||||
position = guiCoord(0.05, 0, 0.3, 0),
|
position = guiCoord(0.05, 0, 0.3, 0),
|
||||||
iconId = "fa:s-info-circle",
|
iconId = "info-circle",
|
||||||
iconType = "faSolid",
|
iconType = "faSolid",
|
||||||
iconColour = globals.defaultColours.primary,
|
iconColour = globals.defaultColours.primary,
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
|
@ -132,7 +132,7 @@ return {
|
||||||
size = guiCoord(0.82, 0, 1, 0),
|
size = guiCoord(0.82, 0, 1, 0),
|
||||||
position = guiCoord(0.15, 0, 0, 0),
|
position = guiCoord(0.15, 0, 0, 0),
|
||||||
text = text,
|
text = text,
|
||||||
fontSize = 16,
|
textSize = 16,
|
||||||
textColour = globals.defaultColours.primary,
|
textColour = globals.defaultColours.primary,
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
textAlign = enums.align.middle,
|
textAlign = enums.align.middle,
|
||||||
|
|
|
@ -24,49 +24,49 @@ return {
|
||||||
|
|
||||||
teverse.construct("guiFrame", {
|
teverse.construct("guiFrame", {
|
||||||
parent = teverse.interface,
|
parent = teverse.interface,
|
||||||
size = guiCoord(0.04, 0, 0.015, 0),
|
size = guiCoord(0, 40, 0, 10),
|
||||||
position = guiCoord(0, 0, 0.05, 0),
|
position = guiCoord(0, 0, 0, 40),
|
||||||
backgroundColour = globals.defaultColours.secondary,
|
backgroundColour = globals.defaultColours.secondary,
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.construct("guiFrame", {
|
teverse.construct("guiFrame", {
|
||||||
parent = teverse.interface,
|
parent = teverse.interface,
|
||||||
size = guiCoord(0.04, 0, 0.015, 0),
|
size = guiCoord(0, 40, 0, 10),
|
||||||
position = guiCoord(0, 0, 0.24, 0),
|
position = guiCoord(0, 0, 0, 180),
|
||||||
backgroundColour = globals.defaultColours.secondary,
|
backgroundColour = globals.defaultColours.secondary,
|
||||||
})
|
})
|
||||||
|
|
||||||
local toolsContainer = teverse.construct("guiFrame", {
|
local toolsContainer = teverse.construct("guiFrame", {
|
||||||
parent = teverse.interface,
|
parent = teverse.interface,
|
||||||
size = guiCoord(0.04, 0, 0.18, 0),
|
size = guiCoord(0, 40, 0, 130),
|
||||||
position = guiCoord(0, 0, 0.065, 0),
|
position = guiCoord(0, 0, 0, 50),
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
})
|
})
|
||||||
|
|
||||||
local selectTool = teverse.construct("guiIcon", {
|
local selectTool = teverse.construct("guiIcon", {
|
||||||
parent = toolsContainer,
|
parent = toolsContainer,
|
||||||
size = guiCoord(0, 20, 0, 20),
|
size = guiCoord(0, 20, 0, 20),
|
||||||
position = guiCoord(0.25, 0, 0.1, 0),
|
position = guiCoord(0.25, 0, 0, 10),
|
||||||
iconId = "location-arrow",
|
iconId = "location-arrow",
|
||||||
iconType = "faSolid",
|
iconType = "faSolid",
|
||||||
iconColour = globals.defaultColours.primary,
|
iconColour = globals.defaultColours.primary,
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
})
|
})
|
||||||
|
|
||||||
local moveTool = teverse.construct("guiIcon", {
|
local moveTool = teverse.construct("guiIcon", {
|
||||||
parent = toolsContainer,
|
parent = toolsContainer,
|
||||||
size = guiCoord(0, 20, 0, 20),
|
size = guiCoord(0, 20, 0, 20),
|
||||||
position = guiCoord(0.25, 0, 0.32, 0),
|
position = guiCoord(0.25, 0, 0, 40),
|
||||||
iconId = "arrows-alt-h",
|
iconId = "arrows-alt-h",
|
||||||
iconType = "faSolid",
|
iconType = "faSolid",
|
||||||
iconColour = globals.defaultColours.primary,
|
iconColour = globals.defaultColours.primary,
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
})
|
})
|
||||||
|
|
||||||
local rotateTool = teverse.construct("guiIcon", {
|
local rotateTool = teverse.construct("guiIcon", {
|
||||||
parent = toolsContainer,
|
parent = toolsContainer,
|
||||||
size = guiCoord(0, 20, 0, 20),
|
size = guiCoord(0, 20, 0, 20),
|
||||||
position = guiCoord(0.25, 0, 0.54, 0),
|
position = guiCoord(0.25, 0, 0, 70),
|
||||||
iconId = "sync",
|
iconId = "sync",
|
||||||
iconType = "faSolid",
|
iconType = "faSolid",
|
||||||
iconColour = globals.defaultColours.primary,
|
iconColour = globals.defaultColours.primary,
|
||||||
|
@ -76,8 +76,8 @@ return {
|
||||||
local sizeTool = teverse.construct("guiIcon", {
|
local sizeTool = teverse.construct("guiIcon", {
|
||||||
parent = toolsContainer,
|
parent = toolsContainer,
|
||||||
size = guiCoord(0, 20, 0, 20),
|
size = guiCoord(0, 20, 0, 20),
|
||||||
position = guiCoord(0.25, 0, 0.76, 0),
|
position = guiCoord(0.25, 0, 0, 100),
|
||||||
iconId = "fa:s-expand",
|
iconId = "expand",
|
||||||
iconType = "faSolid",
|
iconType = "faSolid",
|
||||||
iconColour = globals.defaultColours.primary,
|
iconColour = globals.defaultColours.primary,
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
|
@ -86,8 +86,8 @@ return {
|
||||||
local moreToolsContainer = teverse.construct("guiFrame", {
|
local moreToolsContainer = teverse.construct("guiFrame", {
|
||||||
parent = teverse.interface,
|
parent = teverse.interface,
|
||||||
name = "moreToolsContainer",
|
name = "moreToolsContainer",
|
||||||
size = guiCoord(0.04, 0, 1, 0),
|
size = guiCoord(0, 40, 1, -190),
|
||||||
position = guiCoord(0, 0, 0.255, 0),
|
position = guiCoord(0, 0, 0, 190),
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ return {
|
||||||
parent = page,
|
parent = page,
|
||||||
name = name,
|
name = name,
|
||||||
size = guiCoord(0, 20, 0, 20),
|
size = guiCoord(0, 20, 0, 20),
|
||||||
position = guiCoord((0.25+xPositionOverride), 0, 0.02+(#page.children*0.04), 0), -- Shorthand positioning w/o a for-loop
|
position = guiCoord((0.25+xPositionOverride), 0, 0, 10 + (#page.children*30)), -- Shorthand positioning w/o a for-loop
|
||||||
iconId = icon,
|
iconId = icon,
|
||||||
iconType = "faSolid",
|
iconType = "faSolid",
|
||||||
iconColour = globals.defaultColours.primary,
|
iconColour = globals.defaultColours.primary,
|
||||||
|
@ -158,12 +158,12 @@ return {
|
||||||
--button:mouseLeftPressed(callback) -- When button is clicked, perform callback action
|
--button:mouseLeftPressed(callback) -- When button is clicked, perform callback action
|
||||||
|
|
||||||
-- When mouse hovers over button, display tooltip
|
-- When mouse hovers over button, display tooltip
|
||||||
iconImage:on("mouseFocused", function()
|
iconImage:on("mouseEnter", function()
|
||||||
_tooltip.display()
|
_tooltip.display()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- When mouse leaves from button, hide tooltip
|
-- When mouse leaves from button, hide tooltip
|
||||||
iconImage:on("mouseUnfocused", function()
|
iconImage:on("mouseExit", function()
|
||||||
_tooltip.hide()
|
_tooltip.hide()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,7 +28,7 @@ return {
|
||||||
|
|
||||||
local container = teverse.construct("guiFrame", {
|
local container = teverse.construct("guiFrame", {
|
||||||
parent = teverse.interface,
|
parent = teverse.interface,
|
||||||
size = guiCoord(1, 0, 0.05, 0),
|
size = guiCoord(1, 0, 0, 40),
|
||||||
position = guiCoord(0, 0, 0, 0),
|
position = guiCoord(0, 0, 0, 0),
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
})
|
})
|
||||||
|
@ -50,19 +50,17 @@ return {
|
||||||
position = guiCoord(0.04, 0, 0.05, 0),
|
position = guiCoord(0.04, 0, 0.05, 0),
|
||||||
text = titleValue,
|
text = titleValue,
|
||||||
textColour = globals.defaultColours.primary,
|
textColour = globals.defaultColours.primary,
|
||||||
fontFile = "local:OpenSans-Bold.ttf",
|
textFont = "tevurl:fonts/openSansBold.ttf",
|
||||||
fontSize = 30,
|
textSize = 30
|
||||||
readOnly = true
|
|
||||||
})
|
})
|
||||||
|
|
||||||
teverse.construct("guiTextBox", {
|
teverse.construct("guiTextBox", {
|
||||||
parent = container,
|
parent = container,
|
||||||
size = guiCoord(0.48, 0, 0.1, 0),
|
size = guiCoord(0.48, 0, 0.1, 0),
|
||||||
position = guiCoord(0.86, 0, 0.1, 0),
|
position = guiCoord(0.86, 0, 0.1, 0),
|
||||||
text = globals.user[2],
|
text = globals.user.name,
|
||||||
textColour = globals.defaultColours.primary,
|
textColour = globals.defaultColours.primary,
|
||||||
fontSize = 25,
|
textSize = 25
|
||||||
readOnly = true
|
|
||||||
})
|
})
|
||||||
|
|
||||||
local userIcon = teverse.construct("guiFrame", {
|
local userIcon = teverse.construct("guiFrame", {
|
||||||
|
@ -70,7 +68,7 @@ return {
|
||||||
size = guiCoord(0, 32, 0, 32),
|
size = guiCoord(0, 32, 0, 32),
|
||||||
position = guiCoord(0.82, 0, 0, 0),
|
position = guiCoord(0.82, 0, 0, 0),
|
||||||
backgroundColour = globals.defaultColours.primary,
|
backgroundColour = globals.defaultColours.primary,
|
||||||
borderRadius = 100
|
strokeRadius = 100
|
||||||
})
|
})
|
||||||
|
|
||||||
local statusIcon = teverse.construct("guiFrame", {
|
local statusIcon = teverse.construct("guiFrame", {
|
||||||
|
@ -78,10 +76,10 @@ return {
|
||||||
size = guiCoord(0, 16, 0, 16),
|
size = guiCoord(0, 16, 0, 16),
|
||||||
position = guiCoord(0.836, 0, 0.5, 0),
|
position = guiCoord(0.836, 0, 0.5, 0),
|
||||||
backgroundColour = globals.defaultColours.green,
|
backgroundColour = globals.defaultColours.green,
|
||||||
borderWidth = 2,
|
strokeWidth = 2,
|
||||||
borderColour = globals.defaultColours.white,
|
strokeColour = globals.defaultColours.white,
|
||||||
borderAlpha = 1,
|
strokeAlpha = 1,
|
||||||
borderRadius = 32,
|
strokeRadius = 32,
|
||||||
zIndex = 100
|
zIndex = 100
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -114,7 +112,7 @@ return {
|
||||||
iconColour = globals.defaultColours.primary,
|
iconColour = globals.defaultColours.primary,
|
||||||
backgroundColour = globals.defaultColours.white,
|
backgroundColour = globals.defaultColours.white,
|
||||||
})
|
})
|
||||||
|
local test = self
|
||||||
self.register = function(name, tooltip, page)
|
self.register = function(name, tooltip, page)
|
||||||
--[[
|
--[[
|
||||||
@Description
|
@Description
|
||||||
|
@ -129,21 +127,21 @@ return {
|
||||||
Void, null, nil
|
Void, null, nil
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
table.insert(self.keys, {name})
|
table.insert(test.keys, {name})
|
||||||
local button = teverse.construct("guiButton", {
|
local button = teverse.construct("guiTextBox", {
|
||||||
parent = container,
|
parent = container,
|
||||||
size = guiCoord(0.056, 0, 0.9, 0),
|
size = guiCoord(0.056, 0, 0.9, 0),
|
||||||
position = guiCoord(0.2+(#self.keys*0.07), 0, 0.05, 0),
|
position = guiCoord(0.2+(#test.keys*0.07), 0, 0.05, 0),
|
||||||
text = name,
|
text = name,
|
||||||
textColour = globals.defaultColours.primary,
|
textColour = globals.defaultColours.primary,
|
||||||
fontSize = 30,
|
textSize = 22,
|
||||||
textAlign = enums.align.middle,
|
textAlign = enums.align.middle,
|
||||||
zIndex = 100
|
zIndex = 100
|
||||||
})
|
})
|
||||||
|
|
||||||
local _tooltip = toolTip.construct("vertical", button, tooltip) -- Initialize tooltip instance
|
local _tooltip = toolTip.construct("vertical", button, tooltip) -- Initialize tooltip instance
|
||||||
|
|
||||||
button:mouseLeftPressed(function()
|
button:on("mouseLeftDown", function()
|
||||||
globals.sideBarPageActive.visible = (not globals.sideBarPageActive.visible) -- Unlist active page from view
|
globals.sideBarPageActive.visible = (not globals.sideBarPageActive.visible) -- Unlist active page from view
|
||||||
if globals.sideBarPageActive == page then -- If the same page is clicked twice, unlist and replace with default page
|
if globals.sideBarPageActive == page then -- If the same page is clicked twice, unlist and replace with default page
|
||||||
globals.sideBarPageActive = globals.sideBarPageDefault
|
globals.sideBarPageActive = globals.sideBarPageDefault
|
||||||
|
@ -155,12 +153,12 @@ return {
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- When mouse hovers over button, display tooltip
|
-- When mouse hovers over button, display tooltip
|
||||||
button:on("mouseFocused", function()
|
button:on("mouseEnter", function()
|
||||||
_tooltip.display()
|
_tooltip.display()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- When mouse leaves from button, hide tooltip
|
-- When mouse leaves from button, hide tooltip
|
||||||
button:on("mouseUnfocused", function()
|
button:on("mouseExit", function()
|
||||||
_tooltip.hide()
|
_tooltip.hide()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,7 +44,7 @@ local testPage = sideBar.registerPage("Test") -- Register test page to sidebar i
|
||||||
sideBar.registerIcon(testPage, "consoleIcon", "terminal", " Open console window", nil)
|
sideBar.registerIcon(testPage, "consoleIcon", "terminal", " Open console window", nil)
|
||||||
sideBar.registerIcon(testPage, "playIcon", "play", "Play scene", nil)
|
sideBar.registerIcon(testPage, "playIcon", "play", "Play scene", nil)
|
||||||
sideBar.registerIcon(testPage, "serverIcon", "server", "Configure server", nil)
|
sideBar.registerIcon(testPage, "serverIcon", "server", "Configure server", nil)
|
||||||
sideBar.registerIcon(testPage, "fullScreenIcon", "fullscreen", "Toggle full screen", nil)
|
sideBar.registerIcon(testPage, "fullScreenIcon", "expand-alt", "Toggle full screen", nil)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ return function(dev)
|
||||||
-- If initialize phase fails, prompt to the error screen
|
-- If initialize phase fails, prompt to the error screen
|
||||||
if (not success) then
|
if (not success) then
|
||||||
teverse.interface:destroyChildren()
|
teverse.interface:destroyChildren()
|
||||||
|
|
||||||
local errorScreen = teverse.construct("guiFrame", {
|
local errorScreen = teverse.construct("guiFrame", {
|
||||||
parent = dev.interface,
|
parent = dev.interface,
|
||||||
size = guiCoord(1, 0, 1, 0),
|
size = guiCoord(1, 0, 1, 0),
|
||||||
|
|
Loading…
Reference in New Issue