Compare commits

...

92 Commits

Author SHA1 Message Date
Sanjay Bhadra 68cff74b1f Merge branch 'master' into rewrite-tevx 2020-05-17 10:49:56 -04:00
Jay f4e0ae6139 Merge branch 'master' of https://github.com/teverse/teverse 2020-05-16 17:47:19 +01:00
Jay 6876f15b5c shader 2020-05-16 17:47:15 +01:00
Jay 498cb68083 Shader update 2020-05-16 11:06:31 +01:00
Josh Muir 85dd40e95a Console fixes & tidy up 2020-05-15 22:20:09 +01:00
Josh Muir 5d0584f3cb basic error highlighting 2020-05-15 15:00:32 +01:00
Josh Muir f3129a77a5 Console improvements 2020-05-15 00:39:18 +01:00
Sanjay 3a6b2565f6
Update README.md 2020-05-13 17:56:08 -04:00
Jay 3971aed6a3 feed clip fix 2020-05-13 21:12:27 +01:00
Jay 6efd379391 error message 2020-05-11 20:00:43 +01:00
Jay cf3929e790 02013 Api Dump 2020-05-10 22:09:10 +01:00
Sanjay 8ee1e633e2
Merge pull request #75 from Sanjay-B/master
Remove legacy files / cleanup
2020-05-10 15:32:19 -04:00
Sanjay Bhadra dc2577fb8b Correct vsc merge error 2020-05-10 15:31:22 -04:00
Sanjay Bhadra 547fa8d97b Remove legacy files / directories 2020-05-10 15:26:05 -04:00
Sanjay Bhadra 59e8f168ff Merge remote-tracking branch 'upstream/master' 2020-05-10 15:25:36 -04:00
Sanjay a09916531e
Remove apiDump.json
Replaced by api.json.
2020-05-10 15:23:50 -04:00
Jay 9cc085edf3 update tevgit shortcut 2020-05-10 09:05:06 +01:00
Jay 8c7e69560d changed tevgit shortcut 2020-05-10 08:52:56 +01:00
Jay 90695eee40 tevgit prompt 2020-05-09 22:51:28 +01:00
Jay 858aac9274 display local tevgit notice 2020-05-09 10:35:37 +01:00
Jay 6840ac51c1 variabletutorial 2020-05-09 00:11:25 +01:00
Sanjay Bhadra 5a829404fc Merge remote-tracking branch 'upstream/master' 2020-05-08 18:45:28 -04:00
Jay a554a87f84 added ryan's tutorials 2020-05-08 23:15:01 +01:00
Jay 9f5ad0ee7f Added hover effect to buttons 2020-05-08 22:08:34 +01:00
Sanjay 55a1ca4454
Dashboard wall-feed username modal (#73)
* Refactored Workshop to TevX Format

* Implement flair system + wall feed flair

* Remove unneeded HTTP GET call, restructured newFeedItem()

* Fix posting bug

* Balance branch

* Balance Branch

* Feed user modal

* Fix naming error

* Fix syntax errors

* Fix Syntax Error

* Fixed modal scaling on user prop

* Fixed destoryChildren naming issue

* Fix Modal Positioning

* Fix avatar image modal positioning

Co-authored-by: teverse <43248871+teverse@users.noreply.github.com>
2020-05-08 22:02:13 +01:00
Jay 44c6d455dc Wrap print events in pcall 2020-05-08 20:47:52 +01:00
Jay 1a340567a5 Merge branch 'master' of https://github.com/teverse/teverse 2020-05-08 20:24:18 +01:00
Jay f170c4eac2 0209 api dump 2020-05-08 20:24:16 +01:00
teverse 6d3fcbc08a Console swapperoo 2020-05-08 20:12:14 +01:00
teverse 2da7b377ef added console history 2020-05-08 20:11:32 +01:00
Sanjay Bhadra ac8feee10f Merge remote-tracking branch 'upstream/master' 2020-05-08 13:55:57 -04:00
Jay fa2a04db52 Update API dump 2020-05-07 21:58:39 +01:00
Jay bad6904690 fix api dump type for id 2020-05-07 21:56:41 +01:00
Jay 690b947726 Latest API dump 2020-05-07 21:25:30 +01:00
Sanjay Bhadra 3e3db80ebb Merge remote-tracking branch 'upstream/master' 2020-05-06 01:38:11 -04:00
Jay 6a2ed2629f fix 2020-05-05 22:47:29 +01:00
Jay 17599a6eaf Scrollview scrollbarwidth 2020-05-05 22:41:39 +01:00
Jay cb36ce065a Show pending apps 2020-05-05 21:40:01 +01:00
Jay 9f22dbeda8 Dropshadow for apps and develop 2020-05-05 18:07:13 +01:00
Jay fed726139e Shadows on home? 2020-05-05 18:05:21 +01:00
Jay a4d81aa668 Fixed output size for tutorials 2020-05-05 18:02:15 +01:00
Jay 39fecf6e54 Restructured shader folder 2020-05-05 17:55:54 +01:00
Jay f5346a4383 Tutorial 2020-05-04 22:58:11 +01:00
Sanjay Bhadra 77038455d1 Merge remote-tracking branch 'upstream/master' 2020-05-04 00:52:57 -04:00
Jay b30fbca745 absolute pixel values for sidebar, topbar 2020-05-03 21:57:24 +01:00
Jay 448fb6e37b Fix old use of 0.19 APIs in workshop files 2020-05-03 21:39:26 +01:00
Jay 4c83652c30 improved user generated app notice 2020-05-03 10:44:39 +01:00
Jay 1abb33e965 Disable learn code on iphone for now 2020-05-03 10:34:11 +01:00
Jay 7c30939d24 0.20.7 dump 2020-05-03 09:44:50 +01:00
Sanjay Bhadra 51676c685b Merge remote-tracking branch 'upstream/master' 2020-05-02 20:17:17 -04:00
Sanjay Bhadra 243e654a3f Merge branch 'Sanjay-B-feature-dashboard-wall-users' 2020-05-02 20:14:27 -04:00
Jay 7174736ea9 improved bottom right uii 2020-05-03 00:05:49 +01:00
Sanjay Bhadra 0c0322b855 Feed user modal 2020-05-02 18:48:44 -04:00
Sanjay Bhadra da410f9eef Balance Branch 2020-05-02 18:48:28 -04:00
Jay d859b4b0e1 Tutorial fixes 2020-05-02 23:47:29 +01:00
Jay 14a0f6d3ae Updates to tutorial system 2020-05-02 23:25:40 +01:00
Jay 3d714a1450 Text editor improvements, update to tutorial framework 2020-05-02 21:28:09 +01:00
Jay 378dc7af60 More work on tutorials 2020-05-02 19:05:38 +01:00
Jay 7bd1212552 Fix debug fglag 2020-05-02 15:54:15 +01:00
Jay ca077e22b2 Update plus insignia 2020-05-02 15:53:40 +01:00
Jay 155e2ac581 Hide apps on non dev 2020-05-01 13:28:53 +01:00
Jay 3c2e30b424 tutorial framework start 2020-05-01 13:26:51 +01:00
Jay 74012b5fa8 Script editor padding 2020-04-30 21:49:01 +01:00
Jay eaf899db28 Include 'teverse.sh' 2020-04-30 14:59:49 +01:00
Jay 2e92d94a9f Merge branch 'master' of https://github.com/teverse/teverse 2020-04-29 20:18:55 +01:00
Jay c6e33b743d Added shader 2020-04-29 20:18:52 +01:00
Sanjay 2e0fa7a913
Feature flair system + flair to wall feed (#72)
* Refactored Workshop to TevX Format

* Implement flair system + wall feed flair

* Remove unneeded HTTP GET call, restructured newFeedItem()

* Fix posting bug

* fix vsc conflict errors

* Fix vsc merge conflict error
2020-04-29 20:18:03 +01:00
Jay 1e4e1af8a9 0.20.6 api dump 2020-04-28 23:26:48 +01:00
Jay 740580e6a1 iOS Size fix 2020-04-28 07:56:15 +01:00
Jay 262651e631 Apps on iphone size fix 2 2020-04-28 07:55:41 +01:00
Jay f2bd275687 Apps iphone 2020-04-28 07:55:00 +01:00
Jay 16266ee0b9 Api Dump new parameter structure 2020-04-27 17:36:09 +01:00
Jay 267f97d5d6 Added dump for build 0205 2020-04-27 15:20:21 +01:00
Jay eb69b31e34 Hide develop tab on iPad 2020-04-27 07:55:35 +01:00
Jay a2fbd3032d Script Editor Bug fix 2020-04-26 19:22:43 +01:00
Jay 23c9c1cdb6 Script editor 2020-04-26 18:49:26 +01:00
Jay a9b9d0dec6 Fixed login url 2020-04-26 11:45:37 +01:00
Jay a016fe1676 Special URL for iOS login 2020-04-26 11:44:21 +01:00
Jay b39b953fa6 Added constructable boolean to dump 2020-04-25 22:47:24 +01:00
Jay 4b479a483e Fixed type/desc in dump 2020-04-25 22:25:21 +01:00
Jay 1434cef53f Api Dump fixed parameters 2020-04-25 21:54:29 +01:00
Jay a0fb4dcfb7 Api Dump 2020-04-25 21:35:20 +01:00
Jay 61e3a7347a tev2020 api dump 2020-04-25 21:27:13 +01:00
Jay b676abadef Status bar 2020-04-25 18:48:29 +01:00
Jay 036bbb8ee2 New develop page for tablets 2020-04-25 18:40:02 +01:00
Sanjay Bhadra c4f3c75900 Balance branch 2020-04-25 00:37:32 -04:00
Sanjay Bhadra e042e4b71b Fix posting bug 2020-04-25 00:28:26 -04:00
Sanjay Bhadra 7b49c94906 Remove unneeded HTTP GET call, restructured newFeedItem() 2020-04-24 23:48:17 -04:00
Sanjay Bhadra 1cf50c3fc2 Merge branch 'feature-dashboard-wall' of https://github.com/Sanjay-B/teverse into feature-dashboard-wall 2020-04-24 21:43:00 -04:00
Sanjay Bhadra 02a0068bd5 Merge branch 'master' into feature-dashboard-wall 2020-04-24 21:42:34 -04:00
teverse 519fa3ee76
Merge branch 'master' into feature-dashboard-wall 2020-04-24 09:13:11 +01:00
Sanjay Bhadra 4d7d284a02 Implement flair system + wall feed flair 2020-04-23 18:43:10 -04:00
39 changed files with 4475 additions and 3079 deletions

View File

@ -3,7 +3,7 @@
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
@ -22,4 +22,4 @@ Copyright (c) 2020 teverse.com
# Acknowledgements
- 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

1906
api.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -97,7 +97,7 @@ share:on("mouseLeftUp", function()
if code == 200 then
msg.text = "Your app was updated! Please note apps may be subject to moderation before becoming public."
else
msg.text = "Something went wrong."
msg.text = "Something went wrong: "..code..body
end
end)
end

View File

@ -1,13 +1,19 @@
-- 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,
size = guiCoord(1, 0, 0, 15),
position = guiCoord(0, 0, 1, -15),
backgroundAlpha = 0,
text = "You are running user generated code",
textShadowSize = 4,
textSize = 12,
textColour = colour(1, 1, 1),
textAlign = "middle"
})
size = guiCoord(0, 75, 0, 18),
position = guiCoord(0, 10, 1, -28),
text = "User Content",
textSize = 14,
textColour = colour(0, 0, 0),
textAlign = "middle",
textFont = "tevurl:fonts/openSansSemiBold.ttf",
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05
})
disclaimer:on("mouseLeftUp", function()
teverse.apps:reload()
end)

View File

@ -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 {
name = "Apps",
iconId = "shapes",
@ -29,40 +64,61 @@ return {
local subtitle = teverse.construct("guiTextBox", {
parent = page,
size = guiCoord(1.0, -20, 0, 18),
position = guiCoord(0, 10, 0, 58),
position = guiCoord(0, 10, 0, 105),
backgroundAlpha = 0,
text = "Loading Apps",
textSize = 18,
textAlign = "middleLeft"
})
local appsContainer = teverse.construct("guiFrame", {
local myApps = teverse.construct("guiFrame", {
parent = page,
size = guiCoord(1.0, -20, 1, -100),
position = guiCoord(0, 10, 0, 90),
size = guiCoord(1.0, -20, 0, 38),
position = guiCoord(0, 10, 0, 62),
backgroundAlpha = 0
})
teverse.guiHelper
.gridConstraint(appsContainer, {
cellSize = guiCoord(0, 150, 0, 80),
cellMargin = guiCoord(0, 15, 0, 25)
})
teverse.http:get("https://teverse.com/api/apps", {
teverse.http:get("https://teverse.com/api/users/" .. teverse.networking.localClient.id .. "/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
for i,app in pairs(apps) do
local appGui = teverse.construct("guiFrame", {
parent = appsContainer,
strokeAlpha = 0.1,
strokeRadius = 4
strokeRadius = 2,
dropShadowAlpha = 0.15,
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()
if not loading.visible then
loading.text = "Working..."
@ -81,43 +137,76 @@ return {
end)
end
end)
end
end
end)
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
})
local appsContainer = teverse.construct("guiFrame", {
parent = page,
size = guiCoord(1.0, -20, 1, -140),
position = guiCoord(0, 10, 0, 130),
backgroundAlpha = 0
})
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
})
if _DEVICE:sub(0, 6) == "iPhone" then
teverse.guiHelper
.gridConstraint(appsContainer, {
cellSize = guiCoord(0, page.absoluteSize.x - 20, 0, 50),
cellMargin = guiCoord(0, 15, 0, 25)
})
else
teverse.guiHelper
.gridConstraint(appsContainer, {
cellSize = guiCoord(0, 160, 0, 50),
cellMargin = guiCoord(0, 15, 0, 25)
})
end
teverse.construct("guiIcon", {
parent = appGui,
size = guiCoord(1, 0, 1, -45),
position = guiCoord(0, 0, 0, 45),
iconMax = 20,
iconColour = colour(1, 1, 1),
iconType = "faSolid",
iconId = "code",
iconAlpha = 0.9,
backgroundAlpha = 1.0,
backgroundColour = colour.rgb(216, 100, 89),
active = false
})
if _DEVICE:sub(0, 6) ~= "iPhone" then
local appGui = createApp({
id = "",
name = "Learn Code",
owner = {
username = "Teverse"
}
})
appGui.name = "a"
appGui.parent = appsContainer
appGui:on("mouseLeftUp", function()
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
else
subtitle.text = "Server error."

View File

@ -18,7 +18,9 @@ return {
size = guiCoord(1/3, -20, 0, 70),
position = guiCoord(0, 10, 0, 60),
backgroundColour = colour.rgb(74, 140, 122),
strokeRadius = 3
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05
})
teverse.guiHelper
@ -71,7 +73,9 @@ return {
size = guiCoord(1/3, -20, 0, 70),
position = guiCoord(1/3, 10, 0, 0),
backgroundColour = colour.rgb(74, 140, 122),
strokeRadius = 3
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05
})
teverse.guiHelper

View File

@ -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
}

View File

@ -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", {
size = guiCoord(1, -20, 0, 48),
position = guiCoord(0, 10, 0, 40),
@ -10,22 +128,23 @@ local function newFeedItem(pfp, name, date, body)
name = "profilePicture",
size = guiCoord(0, 30, 0, 30),
position = guiCoord(0, 0, 0, 5),
image = pfp,
image = "tevurl:asset/user/"..(data.postedBy.id),
parent = item,
strokeRadius = 15,
strokeAlpha = 0.04
})
local name = teverse.construct("guiTextBox", {
local username = teverse.construct("guiTextBox", {
name = "username",
size = guiCoord(1, -40, 0, 20),
size = guiCoord(0.8, -50, 0, 20),
position = guiCoord(0, 40, 0, 3),
backgroundAlpha = 0,
parent = item,
text = name,
text = data.postedBy.username,
textSize = 20,
textAlpha = 0.6,
textFont = "tevurl:fonts/openSansBold.ttf"
textFont = "tevurl:fonts/openSansBold.ttf",
zIndex = 500
})
teverse.construct("guiTextBox", {
@ -47,12 +166,88 @@ local function newFeedItem(pfp, name, date, body)
position = guiCoord(0, 40, 0, 22),
backgroundAlpha = 0,
parent = item,
text = body,
text = data.message,
textWrap = true,
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
end
@ -67,7 +262,8 @@ return {
size = guiCoord(1, 0, 1, 50),
position = guiCoord(0, 0, 0, -50),
backgroundAlpha = 0,
strokeRadius = 3
strokeRadius = 3,
scrollbarWidth = 4
})
teverse.guiHelper
@ -87,7 +283,9 @@ return {
size = guiCoord(1/3, -20, 0, 70),
position = guiCoord(0, 10, 0, 0),
backgroundColour = colour.rgb(74, 140, 122),
strokeRadius = 3
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05
})
teverse.guiHelper
@ -144,7 +342,9 @@ return {
size = guiCoord(1/3, -20, 0, 70),
position = guiCoord(1/3, 10, 0, 0),
backgroundColour = colour.rgb(235, 187, 83),
strokeRadius = 3
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05
})
teverse.guiHelper
@ -209,7 +409,9 @@ return {
size = guiCoord(1/3, -20, 0, 70),
position = guiCoord(2/3, 10, 0, 0),
backgroundColour = colour.rgb(216, 100, 89),
strokeRadius = 3
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05
})
teverse.guiHelper
@ -272,7 +474,7 @@ return {
local feedItems = teverse.construct("guiFrame", {
parent = feed,
backgroundAlpha = 0,
clip = true
clip = false
})
teverse.guiHelper
@ -291,12 +493,13 @@ return {
local input = teverse.construct("guiTextBox", {
parent = feedItems,
size = guiCoord(1, -20, 0, 30),
position = guiCoord(0, 10, 0, 10),
strokeAlpha = 0.15,
strokeRadius = 3,
size = guiCoord(1, -2, 0, 30),
position = guiCoord(0, 1, 0, 10),
textEditable = true,
textAlign = "topLeft"
textAlign = "topLeft",
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05
})
local newestFeed = ""
@ -309,9 +512,9 @@ return {
}, function(code, body)
if code == 200 then
lastRefresh = os.clock()
local json = teverse.json:decode(body)
if #json > 0 then
if json[1].id == newestFeed then
local data = teverse.json:decode(body)
if #data > 0 then
if data[1].id == newestFeed then
-- no change from last refresh
return nil
else
@ -322,11 +525,11 @@ return {
end
end
end
newestFeed = json[1].id
newestFeed = data[1].id
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 item = newFeedItem("tevurl:asset/user/" .. v.postedBy.id, v.postedBy.username, date, v.message)
local item = newFeedItem(date, v)
item.parent = feedItems
local dy = item:child("body").textDimensions.y
item.size = guiCoord(1, -20, 0, dy + 28)

View File

@ -113,16 +113,29 @@ controller.setup = function()
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()
for _,v in pairs(pages) do
v[1].visible = false
v[2].iconAlpha = 0.75
v[2].backgroundAlpha = 0.0
v[2].dropShadowAlpha = 0.0
end
container.visible = true
icon.iconAlpha = 1.0
icon.backgroundAlpha = 0.2
icon.dropShadowAlpha = 0.15
end)
page.setup(container)
@ -138,8 +151,12 @@ controller.setup = function()
setupPage(require("tevgit:core/dashboard/pages/home.lua"))
setupPage(require("tevgit:core/dashboard/pages/apps.lua"))
if _DEVICE:sub(0,6) ~= "iPhone" then
setupPage(require("tevgit:core/dashboard/pages/develop.lua"))
if _DEVICE:sub(0, 6) ~= "iPhone" then
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

100
core/editor/editor.lua Normal file
View File

@ -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
}

431
core/editor/lexer.lua Normal file
View File

@ -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

1
core/editor/main.lua Normal file
View File

@ -0,0 +1 @@
local editor = require("tevgit:core/editor/editor.lua").create()

View File

@ -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
}

View File

@ -49,7 +49,13 @@ login.position = guiCoord(0.5, -50, 0.5, 45)
local db = false
local listenerid = login:on("mouseLeftDown", function()
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
sleep(2)
login.visible = true

View File

@ -1,6 +1,6 @@
local container = teverse.construct("guiFrame", {
parent = teverse.coreInterface,
size = guiCoord(0, 300, 0, 400),
size = guiCoord(0.1, 150, 0.4, 200),
position = guiCoord(0, 20, 0, 20),
backgroundAlpha = 0.9,
zIndex = 1000,
@ -14,22 +14,58 @@ teverse.construct("guiTextBox", {
size = guiCoord(1, -10, 0, 20),
position = guiCoord(0, 5, 0, 0),
backgroundAlpha = 0.0,
textSize = 16,
textSize = 20,
textAlign = "middleLeft",
text = "Console"
})
local txt = teverse.construct("guiTextBox", {
local logContainer = teverse.construct("guiScrollView", {
parent = container,
size = guiCoord(1, -10, 1, -25),
size = guiCoord(1, -10, 1, -22),
position = guiCoord(0, 5, 0, 20),
backgroundAlpha = 0.95,
strokeAlpha = 0.2,
textWrap = true
backgroundAlpha = 0.0,
canvasSize = guiCoord(1, -1, 10, 0),
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)
txt.text = string.sub(os.date("%H:%M:%S") .. " : " .. msg .. "\n" .. txt.text, 0, 500)
pcall(function()
addLog(msg)
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

View File

@ -1,82 +1,90 @@
-- 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,
size = guiCoord(0, 77, 0, 26),
position = guiCoord(1, -81, 1, -30),
backgroundAlpha = 0.0,
strokeRadius = 13,
zIndex = 1000
size = guiCoord(1, 0, 0, 50),
position = guiCoord(0, 0, 0, -50),
backgroundColour = colour.black(),
backgroundAlpha = 0.75
})
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", {
parent = container,
size = guiCoord(0, 20, 0, 20),
position = guiCoord(1, -23, 0.5, -10),
local settingsButton = teverse.construct("guiIcon", {
parent = teverse.coreInterface,
size = guiCoord(0, 35, 0, 35),
position = guiCoord(1, -45, 1, -45),
iconId = "wrench",
iconType = "faSolid",
iconColour = colour(0, 0, 0),
iconMax = 12,
iconAlpha = 0.75,
strokeRadius = 10,
strokeAlpha = 0.5,
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05,
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
ico:on("mouseLeftDown", function()
settingsButton:on("mouseLeftUp", function()
if os.clock() - lastClick < 0.4 then
-- double click
lastClick = 0
console.visible = not console.visible
else
lastClick = os.clock()
container.visible = true
repeat sleep(0.1) until teverse.input.mousePosition.y < container.absolutePosition.y - 25
container.visible = false
end
end)
--if teverse.dev.localTevGit then
homebtn = teverse.construct("guiTextBox", {
local homeButton = teverse.construct("guiIcon", {
parent = container,
size = guiCoord(0, 40, 0, 14),
position = guiCoord(0, 6, 0.5, -7),
text = "HOME",
textAlign = "middle",
textFont = "tevurl:fonts/openSansLight.ttf",
textColour = colour(0, 0, 0),
textSize = 14,
strokeRadius = 7,
strokeAlpha = 0.5,
backgroundAlpha = 0,
visible = false
size = guiCoord(0, 35, 0, 35),
position = guiCoord(1, -35, 0, 0),
iconId = "home",
iconType = "faSolid",
iconColour = colour(0, 0, 0),
iconMax = 12,
iconAlpha = 0.75,
strokeRadius = 2,
dropShadowAlpha = 0.15,
strokeAlpha = 0.05,
backgroundAlpha = 1
})
homebtn:on("mouseLeftUp", function()
homeButton:on("mouseLeftUp", function()
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)

View File

@ -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
}

View File

@ -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")
}

View File

@ -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
]]
)
}
}

View File

@ -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),
}
}

View File

@ -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
]]),
}
}

339
core/tutorials/main.lua Normal file
View File

@ -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

48
core/tutorials/output.lua Normal file
View File

@ -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
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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__

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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 isnt 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 users
-- 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!"
}
}

View File

@ -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
}

View File

@ -53,10 +53,10 @@ return {
size = guiCoord(0.95, 0, 0.4, 0),
position = guiCoord(0.025, 0, 0.23, 0),
backgroundColour = globals.defaultColours.white,
borderAlpha = 1,
borderRadius = 5,
borderWidth = 3,
borderColour = globals.defaultColours.secondary
strokeAlpha = 1,
strokeRadius = 5,
strokeWidth = 3,
strokeColour = globals.defaultColours.secondary
})
teverse.construct("guiIcon", {
@ -74,7 +74,7 @@ return {
size = guiCoord(0.82, 0, 1, 0),
position = guiCoord(0.15, 0, 0, 0),
text = text,
fontSize = 16,
textSize = 16,
textColour = globals.defaultColours.primary,
backgroundColour = globals.defaultColours.white,
textAlign = enums.align.middle,
@ -111,17 +111,17 @@ return {
size = guiCoord(0.8, 0, 0.9, 0),
position = guiCoord(0.133, 0, 0.05, 0),
backgroundColour = globals.defaultColours.white,
borderAlpha = 1,
borderRadius = 5,
borderWidth = 3,
borderColour = globals.defaultColours.primary
strokeAlpha = 1,
strokeRadius = 5,
strokeWidth = 3,
strokeColour = globals.defaultColours.primary
})
teverse.construct("guiIcon", {
parent = bodyContainer,
size = guiCoord(0, 16, 0, 16),
position = guiCoord(0.05, 0, 0.3, 0),
iconId = "fa:s-info-circle",
iconId = "info-circle",
iconType = "faSolid",
iconColour = globals.defaultColours.primary,
backgroundColour = globals.defaultColours.white,
@ -132,7 +132,7 @@ return {
size = guiCoord(0.82, 0, 1, 0),
position = guiCoord(0.15, 0, 0, 0),
text = text,
fontSize = 16,
textSize = 16,
textColour = globals.defaultColours.primary,
backgroundColour = globals.defaultColours.white,
textAlign = enums.align.middle,

View File

@ -24,49 +24,49 @@ return {
teverse.construct("guiFrame", {
parent = teverse.interface,
size = guiCoord(0.04, 0, 0.015, 0),
position = guiCoord(0, 0, 0.05, 0),
size = guiCoord(0, 40, 0, 10),
position = guiCoord(0, 0, 0, 40),
backgroundColour = globals.defaultColours.secondary,
})
teverse.construct("guiFrame", {
parent = teverse.interface,
size = guiCoord(0.04, 0, 0.015, 0),
position = guiCoord(0, 0, 0.24, 0),
size = guiCoord(0, 40, 0, 10),
position = guiCoord(0, 0, 0, 180),
backgroundColour = globals.defaultColours.secondary,
})
local toolsContainer = teverse.construct("guiFrame", {
parent = teverse.interface,
size = guiCoord(0.04, 0, 0.18, 0),
position = guiCoord(0, 0, 0.065, 0),
size = guiCoord(0, 40, 0, 130),
position = guiCoord(0, 0, 0, 50),
backgroundColour = globals.defaultColours.white,
})
local selectTool = teverse.construct("guiIcon", {
parent = toolsContainer,
size = guiCoord(0, 20, 0, 20),
position = guiCoord(0.25, 0, 0.1, 0),
position = guiCoord(0.25, 0, 0, 10),
iconId = "location-arrow",
iconType = "faSolid",
iconColour = globals.defaultColours.primary,
backgroundColour = globals.defaultColours.white,
})
local moveTool = teverse.construct("guiIcon", {
parent = toolsContainer,
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",
iconType = "faSolid",
iconColour = globals.defaultColours.primary,
backgroundColour = globals.defaultColours.white,
})
local rotateTool = teverse.construct("guiIcon", {
parent = toolsContainer,
size = guiCoord(0, 20, 0, 20),
position = guiCoord(0.25, 0, 0.54, 0),
position = guiCoord(0.25, 0, 0, 70),
iconId = "sync",
iconType = "faSolid",
iconColour = globals.defaultColours.primary,
@ -76,8 +76,8 @@ return {
local sizeTool = teverse.construct("guiIcon", {
parent = toolsContainer,
size = guiCoord(0, 20, 0, 20),
position = guiCoord(0.25, 0, 0.76, 0),
iconId = "fa:s-expand",
position = guiCoord(0.25, 0, 0, 100),
iconId = "expand",
iconType = "faSolid",
iconColour = globals.defaultColours.primary,
backgroundColour = globals.defaultColours.white,
@ -86,8 +86,8 @@ return {
local moreToolsContainer = teverse.construct("guiFrame", {
parent = teverse.interface,
name = "moreToolsContainer",
size = guiCoord(0.04, 0, 1, 0),
position = guiCoord(0, 0, 0.255, 0),
size = guiCoord(0, 40, 1, -190),
position = guiCoord(0, 0, 0, 190),
backgroundColour = globals.defaultColours.white,
})
@ -146,7 +146,7 @@ return {
parent = page,
name = name,
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,
iconType = "faSolid",
iconColour = globals.defaultColours.primary,
@ -158,12 +158,12 @@ return {
--button:mouseLeftPressed(callback) -- When button is clicked, perform callback action
-- When mouse hovers over button, display tooltip
iconImage:on("mouseFocused", function()
iconImage:on("mouseEnter", function()
_tooltip.display()
end)
-- When mouse leaves from button, hide tooltip
iconImage:on("mouseUnfocused", function()
iconImage:on("mouseExit", function()
_tooltip.hide()
end)
end

View File

@ -28,7 +28,7 @@ return {
local container = teverse.construct("guiFrame", {
parent = teverse.interface,
size = guiCoord(1, 0, 0.05, 0),
size = guiCoord(1, 0, 0, 40),
position = guiCoord(0, 0, 0, 0),
backgroundColour = globals.defaultColours.white,
})
@ -50,19 +50,17 @@ return {
position = guiCoord(0.04, 0, 0.05, 0),
text = titleValue,
textColour = globals.defaultColours.primary,
fontFile = "local:OpenSans-Bold.ttf",
fontSize = 30,
readOnly = true
textFont = "tevurl:fonts/openSansBold.ttf",
textSize = 30
})
teverse.construct("guiTextBox", {
parent = container,
size = guiCoord(0.48, 0, 0.1, 0),
position = guiCoord(0.86, 0, 0.1, 0),
text = globals.user[2],
text = globals.user.name,
textColour = globals.defaultColours.primary,
fontSize = 25,
readOnly = true
textSize = 25
})
local userIcon = teverse.construct("guiFrame", {
@ -70,7 +68,7 @@ return {
size = guiCoord(0, 32, 0, 32),
position = guiCoord(0.82, 0, 0, 0),
backgroundColour = globals.defaultColours.primary,
borderRadius = 100
strokeRadius = 100
})
local statusIcon = teverse.construct("guiFrame", {
@ -78,10 +76,10 @@ return {
size = guiCoord(0, 16, 0, 16),
position = guiCoord(0.836, 0, 0.5, 0),
backgroundColour = globals.defaultColours.green,
borderWidth = 2,
borderColour = globals.defaultColours.white,
borderAlpha = 1,
borderRadius = 32,
strokeWidth = 2,
strokeColour = globals.defaultColours.white,
strokeAlpha = 1,
strokeRadius = 32,
zIndex = 100
})
@ -114,7 +112,7 @@ return {
iconColour = globals.defaultColours.primary,
backgroundColour = globals.defaultColours.white,
})
local test = self
self.register = function(name, tooltip, page)
--[[
@Description
@ -129,21 +127,21 @@ return {
Void, null, nil
]]--
table.insert(self.keys, {name})
local button = teverse.construct("guiButton", {
table.insert(test.keys, {name})
local button = teverse.construct("guiTextBox", {
parent = container,
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,
textColour = globals.defaultColours.primary,
fontSize = 30,
textSize = 22,
textAlign = enums.align.middle,
zIndex = 100
})
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
if globals.sideBarPageActive == page then -- If the same page is clicked twice, unlist and replace with default page
globals.sideBarPageActive = globals.sideBarPageDefault
@ -155,12 +153,12 @@ return {
end)
-- When mouse hovers over button, display tooltip
button:on("mouseFocused", function()
button:on("mouseEnter", function()
_tooltip.display()
end)
-- When mouse leaves from button, hide tooltip
button:on("mouseUnfocused", function()
button:on("mouseExit", function()
_tooltip.hide()
end)
end

View File

@ -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, "playIcon", "play", "Play scene", 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)

View File

@ -61,7 +61,7 @@ return function(dev)
-- If initialize phase fails, prompt to the error screen
if (not success) then
teverse.interface:destroyChildren()
local errorScreen = teverse.construct("guiFrame", {
parent = dev.interface,
size = guiCoord(1, 0, 1, 0),