94 Commits

Author SHA1 Message Date
Robert Jelic
075903f9a9 Small 1.6 fixes
- added basalt.forceRenderUpdate
- fixed dropdowns behaving wrong on monitors
2023-04-29 23:14:19 +02:00
Robert Jelic
d6931412c8 Updated textfield
- fixed paste-events by removing an outdated if-statement
2023-04-17 17:42:11 +02:00
Robert Jelic
73b43358ff Small palette fix 2023-03-11 20:10:06 +01:00
Robert Jelic
df7be99fdd Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2023-02-20 16:28:24 +01:00
Robert Jelic
6f0ddd6bf6 Small fix
Small XML borderColor fix
2023-02-20 16:28:22 +01:00
Robert Jelic
a821abed1f Update Textfield.lua
- Removed buggy selection
- Fixed a small bug
2023-02-17 20:40:49 +01:00
Robert Jelic
50dce1c1e7 added :setSelectionColor()
added :setSelectionColor(backgroundCol, foregroundCol)
2023-01-23 21:52:20 +01:00
Robert Jelic
94fccf9211 Update process.lua 2023-01-08 10:04:00 +01:00
Robert Jelic
a4d0492d17 Update Program.lua 2023-01-08 10:03:39 +01:00
Robert Jelic
5ebb5fe436 Update Program.lua
Fixed args for programs
2023-01-08 10:02:50 +01:00
Robert Jelic
bb921c57cd v1.6.5 2023-01-07 02:31:11 +01:00
Robert Jelic
2b85ab9746 Small fix
Forgot to check if program is active or not
2023-01-01 22:46:34 +01:00
Robert Jelic
29ebd7d4d7 Update Program.lua 2023-01-01 22:24:03 +01:00
Robert Jelic
8ab7bc4bde Auto Resizing fix
Forgot to move code for term_resize events to customEventHandler..
2023-01-01 22:21:52 +01:00
Robert Jelic
1b8f62ce41 schedule filter
Added event filters for schedules, now they should work properly.
2022-12-31 01:42:12 +01:00
Robert Jelic
61e38d89e8 Update images.lua 2022-12-30 02:30:48 +01:00
Robert Jelic
a0db5ecb61 Fixed nfp
Forgot i didn't add nfp support >.<
2022-12-30 02:14:58 +01:00
Robert Jelic
3ef7aa91bf Frame Resize
Forgot to add basalt_resize event for base frames
2022-12-26 15:51:25 +01:00
Robert Jelic
09e8589938 Update install.lua 2022-12-26 12:12:31 +01:00
Robert Jelic
e9aba2498b Small XML Fix
-fixed dyn value for width, height, x and y.
- added bgSymbol and bgSymbolColor for xml
- added texture for xml
2022-12-25 19:12:34 +01:00
Robert Jelic
20ceb6b56f Small event fix for programs 2022-12-25 16:56:13 +01:00
Robert Jelic
6d2956f3bf Updated image docs 2022-12-24 11:48:35 +01:00
Robert Jelic
91e42e096c Update utils.lua 2022-12-24 00:28:07 +01:00
Robert Jelic
5f00dfe401 Update Button.lua 2022-12-19 20:32:35 +01:00
Robert Jelic
2c4c059a70 Fixed a fix
Forgot i have to split by words and not just split when width has reached.
2022-12-18 00:43:09 +01:00
Robert Jelic
923b570d48 CreateText & splitString improvements
Improved the createText and splitString functions.
2022-12-18 00:31:52 +01:00
Robert Jelic
5499057e7e Merge pull request #43 from Erb3/path-6
✏️ Fix small typo ("sotred" -> "stored")
2022-12-16 18:31:21 +01:00
Erlend
d6091b312c ✏️ Fix small typo ("sotred" -> "stored") 2022-12-16 15:28:11 +01:00
Robert Jelic
f19c0ebb49 Update Frame.lua 2022-12-14 20:34:17 +01:00
Robert Jelic
01b83822b1 Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-12-14 20:33:05 +01:00
Robert Jelic
c81f24cca2 Made a small mistake.. 2022-12-14 20:31:01 +01:00
Robert Jelic
ed894cb390 Monitor mouse event fix
Fixed mouse event's on monitor frames not working
2022-12-14 20:25:49 +01:00
Robert Jelic
355db9a82c Merge pull request #42 from Erb3/patch-3
📝 Fix a small typo in How-To.md
2022-12-14 20:10:28 +01:00
Erlend
8112378c70 📝 Fix a small typo in How-To.md
Fixed typo where it said `mainFrame` instead of `main`.
Reported by Broso56#0465 in the Discord.
2022-12-14 15:10:36 +01:00
Robert Jelic
a181496052 Update Frame.lua
This is just a small workaround for an actual bug - i need to figure out where it comes from.
2022-12-09 12:38:20 +01:00
Robert Jelic
636ed0001f Update init.lua
Accidentally changed package.path to nil in certain cases. Oopsie #fixed
2022-12-09 07:18:00 +01:00
Robert Jelic
0e3da7eda5 Update install.lua 2022-11-27 00:47:16 +01:00
Robert Jelic
3cf5adaef1 Add files via upload 2022-11-23 17:52:04 +01:00
Robert Jelic
c0fab23cef Small update to 1.6.4
- added bimg support
- reworked graphic object
- added blit for drawsystem (makes drawing bit faster
- added bimg lib
- reworked image object
- fixed thread bug
2022-11-23 17:32:06 +01:00
Robert Jelic
7609708507 Merge branch 'master' of https://github.com/Pyroxenium/Basalt 2022-11-23 17:11:33 +01:00
Robert Jelic
e2f2a2871d Improved event system
Updated the event system to the current dev branch
2022-11-23 17:11:21 +01:00
Robert Jelic
37dde881ad Small bugfix for frames
Small bugfix for frames when using setZIndex after objects got added. Reason was because the frame didn't add the events to it's parent.
2022-11-22 18:28:03 +01:00
Robert Jelic
8f2e191fe3 Border Bugfix for Buttons
Small visual fix for buttons, when using borders
2022-11-21 06:23:13 +01:00
Robert Jelic
15d8cb3781 Update Object.lua
cancels other events - should never have been there
2022-11-14 06:13:23 +01:00
Robert Jelic
8acb673f74 small hotfix for source project 2022-11-04 21:18:32 +01:00
Robert Jelic
cfdca639db Docs update
some docs update for the new installer
2022-10-31 17:30:11 +01:00
Robert Jelic
b34cdd8383 Small install.lua fix
Small fix to the web version
2022-10-31 00:41:57 +01:00
Robert Jelic
a74b8a3d9f Some smaller changed
some changes for testing improved installer
2022-10-31 00:27:59 +01:00
Robert Jelic
ef480c3998 changed index.html
-added edit-on-github
-added copy code
-added image zoom
- changed search depth from 6 to 2
2022-10-26 00:24:22 +02:00
Robert Jelic
c3e97ae516 Docs -> frames
Updated the frame object in docs
2022-10-26 00:19:00 +02:00
Robert Jelic
d78bb4d141 Docs - panes
changed panes to make it more clear why they exist
2022-10-21 21:13:09 +02:00
Robert Jelic
ab72f244ed Updated some formatting
Updated formatting for object
2022-10-20 21:05:29 +02:00
Robert Jelic
4352d36831 Small docs update
- added searchbar
- added :remove method @Object
2022-10-20 20:20:25 +02:00
Robert Jelic
04ad97ccbe Small program fix 2022-10-20 06:22:14 +02:00
Robert Jelic
6b2433e0a1 Whoops 2022-10-13 20:59:49 +02:00
Robert Jelic
bf1b008084 Docs update
Some more stuff for docs
2022-10-09 14:00:35 +02:00
Robert Jelic
681d54b406 moving module 2022-10-09 12:16:38 +02:00
Robert Jelic
eab8794d38 ..forgot to add (1.6.3)
- Fixed focus system bug
- Fixed :getScrollAmount (frames)
- added :onHover
- added :onLeave
- Made drawing a bit faster
- Added a dragging throttle system
- Mouse events should send now relative coordinates
2022-10-09 12:14:20 +02:00
Robert Jelic
1d3e2018ef docs update
Updated some docs stuff
2022-10-09 12:05:30 +02:00
Robert Jelic
44402b1d26 Basalt 1.6.3 - some improvements
- added new animations (:setMode("animname")
- added :addMode("animname", f) to create custom easings
- Fixed a bug in input when using - or . nothing happens (inputmode number)
- Added a event for labels when using multiple line text and the window/frame gets resized)
- Changed some backend stuff for programs
- added a setEnviroment method for programs
- Added a program_done event and a program_error event for programs (:onError() and :onDone())
- Fixed a bug in textfields (when using editLine it doesn't update colors)
- seperated the char event from the key event (before both events executed :onKey events, now there is a :onChar() and :onKey() event
2022-10-09 10:50:02 +02:00
Robert Jelic
56d89ad6f0 added install/package script
Added install script
Added packager/minify script
2022-09-18 22:21:29 +02:00
Robert Jelic
4af3df72ab Merge pull request #28 from Erb3/master
Docs update, mostly Basalt, Sidebar and Footer.
2022-09-17 15:04:41 +02:00
Erb3
f404e0ad8f Small onEvent change 2022-09-17 14:59:46 +02:00
Erb3
45bb23476b Docs: Fix sidebar issue on all Basalt methods 2022-09-17 14:41:54 +02:00
Erb3
bd61da9593 Docs: basalt.update() 2022-09-17 14:33:10 +02:00
Erb3
9acf7d5345 Docs: Basalt.stopUpdate 2022-09-17 14:33:04 +02:00
Erb3
1efca45639 Docs: Basalt.setVariable.md 2022-09-17 14:28:53 +02:00
Erb3
2dfe69fe43 Docs: Basalt.setTheme 2022-09-17 14:28:44 +02:00
Erb3
40b24ccf46 Docs: Add basalt.setActiveFrame.md 2022-09-17 14:25:01 +02:00
Erb3
1ebeda0375 Docs: Clean up basalt.scheduel.md 2022-09-17 14:21:55 +02:00
Erb3
9a514e6f7c Docs: Add base onEvent.md 2022-09-17 14:21:43 +02:00
Erb3
4f1baee771 Docs: Update basalt.removeFrame.md 2022-09-15 15:34:59 +02:00
Erb3
6ed31dd44c Docs: Update log.md 2022-09-15 15:19:16 +02:00
Erb3
19bc07e350 Docs: Fix typo in basalt.getVariable.md 2022-09-15 15:06:26 +02:00
Erb3
27321380ae Docs: Finish Basalt.getTheme.md 2022-09-15 15:05:42 +02:00
Erb3
bf9f01aae7 Docs: basalt.isKeyDown 2022-09-12 21:07:31 +02:00
Erb3
651690d8ab Docs: basalt.getVariable & basalt.getVersion 2022-09-12 21:04:01 +02:00
Erb3
7bcbafe30b Docs: basalt.getTheme 2022-09-12 20:57:06 +02:00
Erb3
72f2c527b9 Docs: basalt.get(Active)Frame 2022-09-12 20:51:58 +02:00
Erb3
77eeb1ce81 Docs: basalt.debug 2022-09-12 20:47:37 +02:00
Erb3
04d5919a82 Docs: basalt.createFrame 2022-09-12 20:44:18 +02:00
Erb3
6fa519be86 Docs: basalt.autoUpdate() 2022-09-12 20:35:01 +02:00
Erb3
00fff1c2f0 Docs: Basalt.md update
Changes:
* Rewording
* Add forgotten methods
* Sort methods
2022-09-12 20:09:14 +02:00
Erlend
140f1b0014 Reword Quick-Start.md 2022-09-12 12:23:31 +02:00
Erlend
153f2b9146 docs: rephrase installer.md 2022-09-12 12:20:24 +02:00
Erlend
21467fe4f4 Merge pull request #1 from Pyroxenium/master
fetch latest
2022-09-12 11:49:10 +02:00
Robert Jelic
6f372fa070 docs update 2022-09-11 11:40:49 +02:00
Robert Jelic
3ca6ac5af0 small docs fix
someone is watching me
2022-09-10 21:02:56 +02:00
Erlend
ab767e16dd Fix _footer 2022-09-07 16:53:51 +02:00
Erb3
93a0c738fa Make the footer work 2022-09-07 16:51:32 +02:00
Erb3
04d85b633c Undo adding title to sidebar and navbar 2022-09-07 16:29:17 +02:00
Erb3
4d83697537 Update navbar to be consistant 2022-09-07 16:11:53 +02:00
Erb3
ff12c040df Fix formatting in _sidebar.md 2022-09-07 16:07:15 +02:00
Erb3
897b7018a1 [WIKI] Edit wiki home page
Changed made:
* Updated CC:T download link
* Fix <img> into markdown
* Change underscores into astrix
* Fix <a> into markdown
* Remove unnecessary <br>
2022-09-07 16:02:11 +02:00
149 changed files with 24684 additions and 2189 deletions

View File

@@ -1,9 +1,10 @@
local module = require("module")
local Object = require("Object")
local _OBJECTS = require("loadObjects")
local BasaltDraw = require("basaltDraw")
local utils = require("utils")
local layout = require("layout")
local basaltMon = require("basaltMon")
local layout = module("layout")
local basaltMon = module("basaltMon")
local uuid = utils.uuid
local rpairs = utils.rpairs
local xmlValue = utils.getValueFromXML
@@ -48,6 +49,8 @@ return function(name, parent, pTerm, basalt)
local activeEvents = {}
local colorTheme = {}
base:setZIndex(10)
local basaltDraw = BasaltDraw(termObject)
@@ -80,6 +83,7 @@ return function(name, parent, pTerm, basalt)
end
local function getObject(name)
if(type(name)~="string")then name = name.name end
for _, value in pairs(objects) do
for _, b in pairs(value) do
if (b:getName() == name) then
@@ -88,6 +92,7 @@ return function(name, parent, pTerm, basalt)
end
end
end
local function getDeepObject(name)
local o = getObject(name)
if(o~=nil)then return o end
@@ -239,11 +244,11 @@ return function(name, parent, pTerm, basalt)
end
return false
end
local math = math
local function stringToNumber(str)
local ok, err = pcall(load("return " .. str))
local ok, result = pcall(load("return " .. str, "", nil, {math=math}))
if not(ok)then error(str.." is not a valid dynamic code") end
return load("return " .. str)()
return result
end
local function newDynamicValue(_, obj, str)
@@ -326,8 +331,13 @@ return function(name, parent, pTerm, basalt)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:eventHandler("dynamicValueEvent", self)
if(basalt.getDynamicValueEventSetting())then
if (value.eventHandler ~= nil) then
value:eventHandler("basalt_dynamicvalue", self)
end
end
if (value.customEventHandler ~= nil) then
value:customEventHandler("basalt_resize", self)
end
end
end
@@ -339,29 +349,48 @@ return function(name, parent, pTerm, basalt)
return dynamicValues[id][1]
end
local function calculateMaxScroll(self)
local function getVerticalScrollAmount(self)
local amount = 0
for _, value in pairs(objects) do
for _, b in pairs(value) do
if(b.getHeight~=nil)and(b.getY~=nil)then
local h, y = b:getHeight(), b:getY()
if (h + y - self:getHeight() > scrollAmount) then
scrollAmount = max(h + y - self:getHeight(), 0)
if(b:getType()=="Dropdown")then
local h, y = b:getHeight(), b:getY()
local wD, hD = b:getDropdownSize()
h = h + hD - 1
if (h + y - self:getHeight() >= amount) then
amount = max(h + y - self:getHeight(), 0)
end
else
local h, y = b:getHeight(), b:getY()
if (h + y - self:getHeight() >= amount) then
amount = max(h + y - self:getHeight(), 0)
end
end
end
end
end
return amount
end
local function getHorizontalScrollAmount(self)
local amount = 0
for _, value in pairs(objects) do
for _, b in pairs(value) do
if(b.getWidth~=nil)and(b.getX~=nil)then
local h, y = b:getWidth(), b:getX()
if (h + y - self:getWidth() >= amount) then
amount = max(h + y - self:getWidth(), 0)
end
end
end
end
return amount
end
local function focusSystem(self)
if(focusedObject~=focusedObjectCache)then
if(focusedObject~=nil)then
focusedObject:loseFocusHandler()
end
if(focusedObjectCache~=nil)then
focusedObjectCache:getFocusHandler()
end
focusedObject = focusedObjectCache
local function calculateMaxScroll(self)
if(autoScroll)then
scrollAmount = getVerticalScrollAmount(self)
end
end
@@ -385,9 +414,30 @@ return function(name, parent, pTerm, basalt)
return objectType
end;
setZIndex = function(self, newIndex)
base.setZIndex(self, newIndex)
for k,v in pairs(activeEvents)do
if(v)then
self.parent:addEvent(k, self)
end
end
return self
end,
setFocusedObject = function(self, obj)
focusedObjectCache = obj
focusSystem(self)
if(focusedObject~=obj)then
if(focusedObject~=nil)then
if(getObject(focusedObject)~=nil)then
focusedObject:loseFocusHandler()
end
end
if(obj~=nil)then
if(getObject(obj)~=nil)then
obj:getFocusHandler()
end
end
focusedObject = obj
end
return self
end;
@@ -403,8 +453,8 @@ return function(name, parent, pTerm, basalt)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:eventHandler("basalt_resize", value, self)
if (value.customEventHandler ~= nil) then
value:customEventHandler("basalt_resize", self)
end
end
end
@@ -428,17 +478,34 @@ return function(name, parent, pTerm, basalt)
return theme[name] or (self.parent~=nil and self.parent:getTheme(name) or basalt.getTheme(name))
end,
setPosition = function(self, x, y, rel)
base.setPosition(self, x, y, rel)
for _, index in pairs(objZIndex) do
if (objects[index] ~= nil) then
for _, value in pairs(objects[index]) do
if (value.eventHandler ~= nil) then
value:eventHandler("basalt_reposition", value, self)
getThemeColor = function(self, col)
return col~=nil and colorTheme[col] or colorTheme
end,
setThemeColor = function(self, col, ...)
if(self.parent==nil)then
if(self==basalt.getActiveFrame())then
if(type(col)=="string")then
colorTheme[col] = ...
termObject.setPaletteColor(type(col)=="number" and col or colors[col], ...)
elseif(type(col)=="table")then
for k,v in pairs(col)do
colorTheme[k] = v
if(type(v)=="number")then
termObject.setPaletteColor(type(k)=="number" and k or colors[k], v)
else
local r,g,b = table.unpack(v)
termObject.setPaletteColor(type(k)=="number" and k or colors[k], r,g,b)
end
end
end
end
end
return self
end,
setPosition = function(self, x, y, rel)
base.setPosition(self, x, y, rel)
self:recalculateDynamicValues()
return self
end;
@@ -463,8 +530,12 @@ return function(name, parent, pTerm, basalt)
end;
removeFocusedObject = function(self)
focusedObjectCache = nil
focusSystem(self)
if(focusedObject~=nil)then
if(getObject(focusedObject)~=nil)then
focusedObject:loseFocusHandler()
end
end
focusedObject = nil
return self
end;
@@ -527,13 +598,29 @@ return function(name, parent, pTerm, basalt)
getScrollAmount = function(self)
return autoScroll and scrollAmount or calculateMaxScroll(self)
return autoScroll and calculateMaxScroll(self) or scrollAmount
end,
getCalculatedVerticalScroll = getVerticalScrollAmount,
getCalculatedHorizontalScroll = getHorizontalScrollAmount,
show = function(self)
base.show(self)
if(self.parent==nil)then
basalt.setActiveFrame(self)
for k,v in pairs(colors)do
if(type(v)=="number")then
termObject.setPaletteColor(v, colors.packRGB(term.nativePaletteColor((v))))
end
end
for k,v in pairs(colorTheme)do
if(type(v)=="number")then
termObject.setPaletteColor(type(k)=="number" and k or colors[k], v)
else
local r,g,b = table.unpack(v)
termObject.setPaletteColor(type(k)=="number" and k or colors[k], r,g,b)
end
end
if(isMonitor)and not(isGroupedMonitor)then
basalt.setMonitorFrame(monSide, self)
elseif(isGroupedMonitor)then
@@ -548,7 +635,7 @@ return function(name, parent, pTerm, basalt)
hide = function (self)
base.hide(self)
if(self.parent==nil)then
if(activeFrame == self)then activeFrame = nil end -- bug activeFrame always nil
if(activeFrame == self)then activeFrame = nil end
if(isMonitor)and not(isGroupedMonitor)then
if(basalt.getMonitorFrame(monSide) == self)then
basalt.setActiveFrame(nil)
@@ -732,16 +819,14 @@ return function(name, parent, pTerm, basalt)
if(focusedObject~=nil)then focusedObject:getFocusHandler() end
end;
eventHandler = function(self, event, p1, p2, p3, p4)
base.eventHandler(self, event, p1, p2, p3, p4)
eventHandler = function(self, event, ...)
base.eventHandler(self, event, ...)
if(events["other_event"]~=nil)then
for _, index in ipairs(eventZIndex["other_event"]) do
if (events["other_event"][index] ~= nil) then
for _, value in rpairs(events["other_event"][index]) do
if (value.eventHandler ~= nil) then
if (value:eventHandler(event, p1, p2, p3, p4)) then
return true
end
value:eventHandler(event, ...)
end
end
end
@@ -750,6 +835,7 @@ return function(name, parent, pTerm, basalt)
if(autoSize)and not(isMonitor)then
if(self.parent==nil)then
if(event=="term_resize")then
self:sendEvent("basalt_resize", self, event, ...)
self:setSize(termObject.getSize())
autoSize = true
end
@@ -797,26 +883,23 @@ return function(name, parent, pTerm, basalt)
self:mouseHandler(1, p2, p3, true)
end
end
if (event == "terminate")and(self.parent==nil)then
basalt.stop()
end
end,
mouseHandler = function(self, button, x, y, _, side)
mouseHandler = function(self, button, x, y, touch, side)
if(isGroupedMonitor)then
if(termObject.calculateClick~=nil)then
x, y = termObject.calculateClick(side, x, y)
end
end
if(base.mouseHandler(self, button, x, y))then
if(base.mouseHandler(self, button, x, y, touch))then
if(events["mouse_click"]~=nil)then
self:setCursor(false)
for _, index in ipairs(eventZIndex["mouse_click"]) do
if (events["mouse_click"][index] ~= nil) then
for _, value in rpairs(events["mouse_click"][index]) do
if (value.mouseHandler ~= nil) then
if (value:mouseHandler(button, x, y)) then
focusSystem(self)
if (value:mouseHandler(button, x, y, touch)) then
return true
end
end
@@ -849,7 +932,6 @@ return function(name, parent, pTerm, basalt)
for _, value in rpairs(events["mouse_up"][index]) do
if (value.mouseUpHandler ~= nil) then
if (value:mouseUpHandler(button, x, y)) then
focusSystem(self)
return true
end
end
@@ -857,7 +939,6 @@ return function(name, parent, pTerm, basalt)
end
end
end
focusSystem(self)
return true
end
return false
@@ -871,7 +952,6 @@ return function(name, parent, pTerm, basalt)
for _, value in rpairs(events["mouse_scroll"][index]) do
if (value.scrollHandler ~= nil) then
if (value:scrollHandler(dir, x, y)) then
focusSystem(self)
return true
end
end
@@ -887,13 +967,32 @@ return function(name, parent, pTerm, basalt)
self:updateDraw()
end
end
self:removeFocusedObject()
if(yOffset==cache)then return false end
self:removeFocusedObject()
return true
end
return false
end,
hoverHandler = function(self, x, y, stopped)
if(base.hoverHandler(self, x, y, stopped))then
if(events["mouse_move"]~=nil)then
for _, index in pairs(eventZIndex["mouse_move"]) do
if (events["mouse_move"][index] ~= nil) then
for _, value in rpairs(events["mouse_move"][index]) do
if (value.hoverHandler ~= nil) then
if (value:hoverHandler(x, y, stopped)) then
return true
end
end
end
end
end
end
end
return false
end,
dragHandler = function(self, button, x, y)
if (isDragging) then
local xO, yO = self.parent:getOffsetInternal()
@@ -915,7 +1014,6 @@ return function(name, parent, pTerm, basalt)
for _, value in rpairs(events["mouse_drag"][index]) do
if (value.dragHandler ~= nil) then
if (value:dragHandler(button, x, y)) then
focusSystem(self)
return true
end
end
@@ -924,7 +1022,7 @@ return function(name, parent, pTerm, basalt)
end
end
end
focusSystem(self)
base.dragHandler(self, button, x, y)
return false
end,
@@ -1036,6 +1134,24 @@ return function(name, parent, pTerm, basalt)
end
end;
blit = function (self, x, y, t, f, b)
local obx, oby = self:getAnchorPosition()
if (y >= 1) and (y <= self:getHeight()) then
local w = self:getWidth()
if (self.parent ~= nil) then
t = sub(t, max(1 - x + 1, 1), w - x + 1)
f = sub(f, max(1 - x + 1, 1), w - x + 1)
b = sub(b, max(1 - x + 1, 1), w - x + 1)
self.parent:blit(max(x + (obx - 1), obx), oby + y - 1, t, f, b)
else
t = sub(t, max(1 - x + 1, 1), max(w - x + 1,1))
f = sub(f, max(1 - x + 1, 1), max(w - x + 1,1))
b = sub(b, max(1 - x + 1, 1), max(w - x + 1,1))
basaltDraw.blit(max(x + (obx - 1), obx), oby + y - 1, t, f, b)
end
end
end,
drawBackgroundBox = function(self, x, y, width, height, bgCol)
local obx, oby = self:getAnchorPosition()

View File

@@ -1,9 +1,13 @@
local basaltEvent = require("basaltEvent")
local utils = require("utils")
local module = require("module")
local images = module("images")
local split = utils.splitString
local numberFromString = utils.numberFromString
local xmlValue = utils.getValueFromXML
local unpack,sub = table.unpack,string.sub
return function(name)
-- Base object
local objectType = "Object" -- not changeable
@@ -14,6 +18,8 @@ return function(name)
local ignOffset = false
local isVisible = true
local initialized = false
local isHovered = false
local isClicked = false
local shadow = false
local borderColors = {
@@ -28,6 +34,13 @@ return function(name)
local isDragging = false
local dragStartX, dragStartY, dragXOffset, dragYOffset = 0, 0, 0, 0
local bimg
local texture
local textureId = 1
local textureTimerId
local textureMode
local infinitePlay = true
local draw = true
local activeEvents = {}
@@ -95,11 +108,25 @@ return function(name)
setValuesByXMLData = function(self, data)
local baseFrame = self:getBaseFrame()
if(xmlValue("x", data)~=nil)then self:setPosition(xmlValue("x", data), self.y) end
if(xmlValue("y", data)~=nil)then self:setPosition(self.x, xmlValue("y", data)) end
if(xmlValue("width", data)~=nil)then self:setSize(xmlValue("width", data), self.height) end
if(xmlValue("height", data)~=nil)then self:setSize(self.width, xmlValue("height", data)) end
local tex, mode, infPlay
if(xmlValue("texture", data)~=nil)then tex = xmlValue("texture", data) end
if(xmlValue("mode", data)~=nil)then mode = xmlValue("mode", data) end
if(xmlValue("texturePlay", data)~=nil)then infPlay = xmlValue("texturePlay", data) end
local x, y
if(xmlValue("x", data)~=nil)then x = xmlValue("x", data) end
if(xmlValue("y", data)~=nil)then y = xmlValue("y", data) end
if(x~=nil)or(y~=nil)then
self:setPosition(x, y)
end
local w, h
if(xmlValue("width", data)~=nil)then w = xmlValue("width", data) end
if(xmlValue("height", data)~=nil)then h = xmlValue("height", data) end
if(w~=nil)or(h~=nil)then
self:setSize(w, h)
end
if(xmlValue("bg", data)~=nil)then self:setBackground(colors[xmlValue("bg", data)]) end
if(xmlValue("bgSymbol", data)~=nil)then self:setBackground(self.bgColor, xmlValue("bgSymbol", data)) end
if(xmlValue("bgSymbolColor", data)~=nil)then self:setBackground(self.bgColor, self.bgSymbol, colors[xmlValue("bgSymbolColor", data)]) end
if(xmlValue("fg", data)~=nil)then self:setForeground(colors[xmlValue("fg", data)]) end
if(xmlValue("value", data)~=nil)then self:setValue(colors[xmlValue("value", data)]) end
if(xmlValue("visible", data)~=nil)then if(xmlValue("visible", data))then self:show() else self:hide() end end
@@ -108,16 +135,18 @@ return function(name)
if(xmlValue("anchor", data)~=nil)then self:setAnchor(xmlValue("anchor", data)) end
if(xmlValue("shadowColor", data)~=nil)then self:setShadow(colors[xmlValue("shadowColor", data)]) end
if(xmlValue("border", data)~=nil)then self:setBorder(colors[xmlValue("border", data)]) end
if(xmlValue("borderLeft", data)~=nil)then borderColors["left"] = xmlValue("borderLeft", data) end
if(xmlValue("borderTop", data)~=nil)then borderColors["top"] = xmlValue("borderTop", data) end
if(xmlValue("borderRight", data)~=nil)then borderColors["right"] = xmlValue("borderRight", data) end
if(xmlValue("borderBottom", data)~=nil)then borderColors["bottom"] = xmlValue("borderBottom", data) end
if(xmlValue("borderLeft", data)~=nil)then borderColors["left"] = colors[xmlValue("borderLeft", data)] end
if(xmlValue("borderTop", data)~=nil)then borderColors["top"] = colors[xmlValue("borderTop", data)] end
if(xmlValue("borderRight", data)~=nil)then borderColors["right"] = colors[xmlValue("borderRight", data)] end
if(xmlValue("borderBottom", data)~=nil)then borderColors["bottom"] = colors[xmlValue("borderBottom", data)] end
if(xmlValue("borderColor", data)~=nil)then self:setBorder(colors[xmlValue("borderColor", data)]) end
if(xmlValue("ignoreOffset", data)~=nil)then if(xmlValue("ignoreOffset", data))then self:ignoreOffset(true) end end
if(xmlValue("onClick", data)~=nil)then self:generateXMLEventFunction(self.onClick, xmlValue("onClick", data)) end
if(xmlValue("onClickUp", data)~=nil)then self:generateXMLEventFunction(self.onClickUp, xmlValue("onClickUp", data)) end
if(xmlValue("onScroll", data)~=nil)then self:generateXMLEventFunction(self.onScroll, xmlValue("onScroll", data)) end
if(xmlValue("onDrag", data)~=nil)then self:generateXMLEventFunction(self.onDrag, xmlValue("onDrag", data)) end
if(xmlValue("onHover", data)~=nil)then self:generateXMLEventFunction(self.onHover, xmlValue("onHover", data)) end
if(xmlValue("onLeave", data)~=nil)then self:generateXMLEventFunction(self.onLeave, xmlValue("onLeave", data)) end
if(xmlValue("onKey", data)~=nil)then self:generateXMLEventFunction(self.onKey, xmlValue("onKey", data)) end
if(xmlValue("onKeyUp", data)~=nil)then self:generateXMLEventFunction(self.onKeyUp, xmlValue("onKeyUp", data)) end
if(xmlValue("onChange", data)~=nil)then self:generateXMLEventFunction(self.onChange, xmlValue("onChange", data)) end
@@ -126,6 +155,9 @@ return function(name)
if(xmlValue("onEvent", data)~=nil)then self:generateXMLEventFunction(self.onEvent, xmlValue("onEvent", data)) end
if(xmlValue("onGetFocus", data)~=nil)then self:generateXMLEventFunction(self.onGetFocus, xmlValue("onGetFocus", data)) end
if(xmlValue("onLoseFocus", data)~=nil)then self:generateXMLEventFunction(self.onLoseFocus, xmlValue("onLoseFocus", data)) end
if(tex~=nil)then
self:setTexture(tex, mode, infPlay)
end
self:updateDraw()
return self
end,
@@ -191,11 +223,13 @@ return function(name)
return self
end;
setValue = function(self, _value)
setValue = function(self, _value, valueChangedHandler)
if (value ~= _value) then
value = _value
self:updateDraw()
self:valueChangedHandler()
if(valueChangedHandler~=false)then
self:valueChangedHandler()
end
end
return self
end;
@@ -241,7 +275,7 @@ return function(name)
end
self.parent:recalculateDynamicValues()
end
eventSystem:sendEvent("basalt_reposition", self)
self:customEventHandler("basalt_reposition")
self:updateDraw()
return self
end;
@@ -270,10 +304,10 @@ return function(name)
setSize = function(self, width, height, rel)
if(type(width)=="number")then
self.width = rel and self.width+width or width
self.width = rel and self:getWidth()+width or width
end
if(type(height)=="number")then
self.height = rel and self.height+height or height
self.height = rel and self:getHeight()+height or height
end
if(self.parent~=nil)then
if(type(width)=="string")then
@@ -284,24 +318,27 @@ return function(name)
end
self.parent:recalculateDynamicValues()
end
eventSystem:sendEvent("basalt_resize", self)
if(bimg~=nil)and(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[textureId]
end
self:customEventHandler("basalt_resize")
self:updateDraw()
return self
end;
end,
getHeight = function(self)
return type(self.height) == "number" and self.height or math.floor(self.height[1]+0.5)
end;
end,
getWidth = function(self)
return type(self.width) == "number" and self.width or math.floor(self.width[1]+0.5)
end;
end,
getSize = function(self)
return self:getWidth(), self:getHeight()
end;
end,
calculateDynamicValues = function(self)
calculateDynamicValues = function(self)
if(type(self.width)=="table")then self.width:calculate() end
if(type(self.height)=="table")then self.height:calculate() end
if(type(self.x)=="table")then self.x:calculate() end
@@ -316,12 +353,38 @@ return function(name)
self.bgSymbolColor = symbolCol or self.bgSymbolColor
self:updateDraw()
return self
end;
end,
setTexture = function(self, tex, mode, infPlay)
if(type(tex)=="string")then
bimg = images.loadImageAsBimg(tex)
elseif(type(tex)=="table")then
bimg = tex
end
if(bimg.animated)then
local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
self.parent:addEvent("other_event", self)
activeEvents["other_event"] = true
end
infinitePlay = infPlay==false and false or true
textureId = 1
textureMode = mode or "normal"
if(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[1]
else
texture = bimg[1]
end
self:updateDraw()
return self
end,
setTransparent = function(self, color)
self.transparentColor = color or false
self.bgSymbol = false
self.bgSymbolColor = false
if(color~=false)then
self.bgSymbol = false
self.bgSymbolColor = false
end
self:updateDraw()
return self
end;
@@ -399,64 +462,97 @@ return function(name)
local w,h = self:getSize()
local wP,hP = self.parent:getSize()
if(x+w<1)or(x>wP)or(y+h<1)or(y>hP)then return false end
if(self.transparentColor~=false)then
self.parent:drawForegroundBox(x, y, w, h, self.transparentColor)
end
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(x, y, w, h, self.bgColor)
end
if(self.bgSymbol~=false)then
self.parent:drawTextBox(x, y, w, h, self.bgSymbol)
if(self.bgSymbol~=" ")then
self.parent:drawForegroundBox(x, y, w, h, self.bgSymbolColor)
if(self.transparentColor~=false)then
self.parent:drawForegroundBox(x, y, w, h, self.transparentColor)
end
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(x, y, w, h, self.bgColor)
end
if(self.bgSymbol~=false)then
self.parent:drawTextBox(x, y, w, h, self.bgSymbol)
if(self.bgSymbol~=" ")then
self.parent:drawForegroundBox(x, y, w, h, self.bgSymbolColor)
end
end
if(texture~=nil)then
if(textureMode=="center")then
local tW,tH = #texture[1][1],#texture
local xO = tW < w and math.floor((w-tW)/2) or 0
local yO = tH < h and math.floor((h-tH)/2) or 0
local sL = tW<w and 1 or math.floor((tW-w)/2)
local eL = tW<w and w or w - math.floor((w-tW)/2+0.5)-1
local sH = tH<h and 1 or math.floor((tH-h)/2)
local eH = tH<h and h or h - math.floor((h-tH)/2+0.5)-1
local yTex = 1
for k=sH,#texture do
if(texture[k]~=nil)then
local t, f, b = unpack(texture[k])
t = sub(t, sL,eL)
f = sub(f, sL,eL)
b = sub(b, sL,eL)
self.parent:blit(x+xO, y+yTex-1+yO, t, f, b)
end
yTex = yTex + 1
if(k==eH)then break end
end
else
for k,v in pairs(texture)do
local t, f, b = unpack(v)
t = sub(t, 1,w)
f = sub(f, 1,w)
b = sub(b, 1,w)
self.parent:blit(x, y+k-1, t, f, b)
if(k==h)then break end
end
end
end
end
if(shadow)then
self.parent:drawBackgroundBox(x+1, y+h, w, 1, shadowColor)
self.parent:drawBackgroundBox(x+w, y+1, 1, h, shadowColor)
self.parent:drawForegroundBox(x+1, y+h, w, 1, shadowColor)
self.parent:drawForegroundBox(x+w, y+1, 1, h, shadowColor)
end
local bgCol = self.bgColor
if(borderColors["left"]~=false)then
self.parent:drawTextBox(x-1, y, 1, h, "\149")
self.parent:drawBackgroundBox(x-1, y, 1, h, self.bgColor)
self.parent:drawForegroundBox(x-1, y, 1, h, borderColors["left"])
end
if(borderColors["left"]~=false)and(borderColors["top"]~=false)then
self.parent:drawTextBox(x-1, y-1, 1, 1, "\151")
self.parent:drawBackgroundBox(x-1, y-1, 1, 1, self.bgColor)
self.parent:drawForegroundBox(x-1, y-1, 1, 1, borderColors["left"])
self.parent:drawTextBox(x, y, 1, h, "\149")
if(bgCol~=false)then self.parent:drawBackgroundBox(x, y, 1, h, bgCol) end
self.parent:drawForegroundBox(x, y, 1, h, borderColors["left"])
end
if(borderColors["top"]~=false)then
self.parent:drawTextBox(x, y-1, w, 1, "\131")
self.parent:drawBackgroundBox(x, y-1, w, 1, self.bgColor)
self.parent:drawForegroundBox(x, y-1, w, 1, borderColors["top"])
self.parent:drawTextBox(x, y, w, 1, "\131")
if(bgCol~=false)then self.parent:drawBackgroundBox(x, y, w, 1, self.bgColor) end
self.parent:drawForegroundBox(x, y, w, 1, borderColors["top"])
end
if(borderColors["top"]~=false)and(borderColors["right"]~=false)then
self.parent:drawTextBox(x+w, y-1, 1, 1, "\148")
self.parent:drawForegroundBox(x+w, y-1, 1, 1, self.bgColor)
self.parent:drawBackgroundBox(x+w, y-1, 1, 1, borderColors["right"])
if(borderColors["left"]~=false)and(borderColors["top"]~=false)then
self.parent:drawTextBox(x, y, 1, 1, "\151")
if(bgCol~=false)then self.parent:drawBackgroundBox(x, y, 1, 1, self.bgColor) end
self.parent:drawForegroundBox(x, y, 1, 1, borderColors["left"])
end
if(borderColors["right"]~=false)then
self.parent:drawTextBox(x+w, y, 1, h, "\149")
self.parent:drawForegroundBox(x+w, y, 1, h, self.bgColor)
self.parent:drawBackgroundBox(x+w, y, 1, h, borderColors["right"])
end
if(borderColors["right"]~=false)and(borderColors["bottom"]~=false)then
self.parent:drawTextBox(x+w, y+h, 1, 1, "\133")
self.parent:drawForegroundBox(x+w, y+h, 1, 1, self.bgColor)
self.parent:drawBackgroundBox(x+w, y+h, 1, 1, borderColors["right"])
self.parent:drawTextBox(x+w-1, y, 1, h, "\149")
if(bgCol~=false)then self.parent:drawForegroundBox(x+w-1, y, 1, h, self.bgColor) end
self.parent:drawBackgroundBox(x+w-1, y, 1, h, borderColors["right"])
end
if(borderColors["bottom"]~=false)then
self.parent:drawTextBox(x, y+h, w, 1, "\143")
self.parent:drawForegroundBox(x, y+h, w, 1, self.bgColor)
self.parent:drawBackgroundBox(x, y+h, w, 1, borderColors["bottom"])
self.parent:drawTextBox(x, y+h-1, w, 1, "\143")
if(bgCol~=false)then self.parent:drawForegroundBox(x, y+h-1, w, 1, self.bgColor) end
self.parent:drawBackgroundBox(x, y+h-1, w, 1, borderColors["bottom"])
end
if(borderColors["top"]~=false)and(borderColors["right"]~=false)then
self.parent:drawTextBox(x+w-1, y, 1, 1, "\148")
if(bgCol~=false)then self.parent:drawForegroundBox(x+w-1, y, 1, 1, self.bgColor) end
self.parent:drawBackgroundBox(x+w-1, y, 1, 1, borderColors["right"])
end
if(borderColors["right"]~=false)and(borderColors["bottom"]~=false)then
self.parent:drawTextBox(x+w-1, y+h-1, 1, 1, "\133")
if(bgCol~=false)then self.parent:drawForegroundBox(x+w-1, y+h-1, 1, 1, self.bgColor) end
self.parent:drawBackgroundBox(x+w-1, y+h-1, 1, 1, borderColors["right"])
end
if(borderColors["bottom"]~=false)and(borderColors["left"]~=false)then
self.parent:drawTextBox(x-1, y+h, 1, 1, "\138")
self.parent:drawForegroundBox(x-1, y+h, 1, 1, self.bgColor)
self.parent:drawBackgroundBox(x-1, y+h, 1, 1, borderColors["left"])
self.parent:drawTextBox(x, y+h-1, 1, 1, "\138")
if(bgCol~=false)then self.parent:drawForegroundBox(x-1, y+h-1, 1, 1, self.bgColor) end
self.parent:drawBackgroundBox(x, y+h-1, 1, 1, borderColors["left"])
end
end
draw = false
@@ -560,6 +656,8 @@ return function(name)
if(self.parent~=nil)then
self.parent:addEvent("mouse_click", self)
activeEvents["mouse_click"] = true
self.parent:addEvent("mouse_up", self)
activeEvents["mouse_up"] = true
end
return self
end;
@@ -571,26 +669,68 @@ return function(name)
end
end
if(self.parent~=nil)then
self.parent:addEvent("mouse_click", self)
activeEvents["mouse_click"] = true
self.parent:addEvent("mouse_up", self)
activeEvents["mouse_up"] = true
end
return self
end;
onScroll = function(self, ...)
onRelease = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_scroll", v)
self:registerEvent("mouse_release", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("mouse_scroll", self)
activeEvents["mouse_scroll"] = true
self.parent:addEvent("mouse_click", self)
activeEvents["mouse_click"] = true
self.parent:addEvent("mouse_up", self)
activeEvents["mouse_up"] = true
end
return self
end;
onScroll = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_scroll", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("mouse_scroll", self)
activeEvents["mouse_scroll"] = true
end
return self
end;
onHover = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_hover", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("mouse_move", self)
activeEvents["mouse_move"] = true
end
return self
end;
onLeave = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("mouse_leave", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("mouse_move", self)
activeEvents["mouse_move"] = true
end
return self
end;
onDrag = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
@@ -626,13 +766,25 @@ return function(name)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("key", v)
self:registerEvent("char", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("key", self)
self.parent:addEvent("char", self)
activeEvents["key"] = true
end
end
return self
end;
onChar = function(self, ...)
if(isEnabled)then
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("char", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("char", self)
activeEvents["char"] = true
end
end
@@ -717,7 +869,8 @@ return function(name)
isCoordsInObject = function(self, x, y)
if(isVisible)and(isEnabled)then
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
if(x==nil)or(y==nil)then return false end
local objX, objY = self:getAbsolutePosition()
local w, h = self:getSize()
if (objX <= x) and (objX + w > x) and (objY <= y) and (objY + h > y) then
return true
@@ -728,11 +881,13 @@ return function(name)
mouseHandler = function(self, button, x, y, isMon)
if(self:isCoordsInObject(x, y))then
local val = eventSystem:sendEvent("mouse_click", self, "mouse_click", button, x, y, isMon)
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_click", self, "mouse_click", button, x - (objX-1), y - (objY-1), x, y, isMon)
if(val==false)then return false end
if(self.parent~=nil)then
self.parent:setFocusedObject(self)
end
isClicked = true
isDragging = true
dragStartX, dragStartY = x, y
return true
@@ -742,8 +897,14 @@ return function(name)
mouseUpHandler = function(self, button, x, y)
isDragging = false
if(isClicked)then
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_release", self, "mouse_release", button, x - (objX-1), y - (objY-1), x, y)
isClicked = false
end
if(self:isCoordsInObject(x, y))then
local val = eventSystem:sendEvent("mouse_up", self, "mouse_up", button, x, y)
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_up", self, "mouse_up", button, x - (objX-1), y - (objY-1), x, y)
if(val==false)then return false end
return true
end
@@ -752,16 +913,8 @@ return function(name)
dragHandler = function(self, button, x, y)
if(isDragging)then
local xO, yO, parentX, parentY = 0, 0, 1, 1
if (self.parent ~= nil) then
xO, yO = self.parent:getOffsetInternal()
xO = xO < 0 and math.abs(xO) or -xO
yO = yO < 0 and math.abs(yO) or -yO
parentX, parentY = self.parent:getAbsolutePosition(self.parent:getAnchorPosition())
end
local dX, dY = x + dragXOffset - (parentX - 1) + xO, y + dragYOffset - (parentY - 1) + yO
local val = eventSystem:sendEvent("mouse_drag", self, button, dX, dY, dragStartX-x, dragStartY-y, x, y)
local objX, objY = self:getAbsolutePosition(self:getAnchorPosition())
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_drag", self, "mouse_drag", button, x - (objX-1), y - (objY-1), dragStartX-x, dragStartY-y, x, y)
dragStartX, dragStartY = x, y
if(val~=nil)then return val end
if(self.parent~=nil)then
@@ -780,7 +933,8 @@ return function(name)
scrollHandler = function(self, dir, x, y)
if(self:isCoordsInObject(x, y))then
local val = eventSystem:sendEvent("mouse_scroll", self, "mouse_scroll", dir, x, y)
local objX, objY = self:getAbsolutePosition()
local val = eventSystem:sendEvent("mouse_scroll", self, "mouse_scroll", dir, x - (objX-1), y - (objY-1))
if(val==false)then return false end
if(self.parent~=nil)then
self.parent:setFocusedObject(self)
@@ -790,6 +944,21 @@ return function(name)
return false
end,
hoverHandler = function(self, x, y, stopped)
if(self:isCoordsInObject(x, y))then
local val = eventSystem:sendEvent("mouse_hover", self, "mouse_hover", x, y, stopped)
if(val==false)then return false end
isHovered = true
return true
end
if(isHovered)then
local val = eventSystem:sendEvent("mouse_leave", self, "mouse_leave", x, y, stopped)
if(val==false)then return false end
isHovered = false
end
return false
end,
keyHandler = function(self, key, isHolding)
if(isEnabled)and(isVisible)then
if (self:isFocused()) then
@@ -815,7 +984,7 @@ return function(name)
charHandler = function(self, char)
if(isEnabled)and(isVisible)then
if (self:isFocused()) then
local val = eventSystem:sendEvent("char", self, "char", char)
local val = eventSystem:sendEvent("char", self, "char", char)
if(val==false)then return false end
return true
end
@@ -827,8 +996,42 @@ return function(name)
eventSystem:sendEvent("value_changed", self, value)
end;
eventHandler = function(self, event, p1, p2, p3, p4)
local val = eventSystem:sendEvent("other_event", self, event, p1, p2, p3, p4)
eventHandler = function(self, event, ...)
local args = {...}
if(event=="timer")and(args[1]==textureTimerId)then
if(bimg[textureId+1]~=nil)then
textureId = textureId + 1
if(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[textureId]
else
texture = bimg[textureId]
end
local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
else
if(infinitePlay)then
textureId = 1
if(textureMode=="stretch")then
texture = images.resizeBIMG(bimg, self:getSize())[1]
else
texture = bimg[1]
end
local t = bimg[1].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
end
end
self:updateDraw()
end
local val = eventSystem:sendEvent("other_event", self, event, ...)
if(val~=nil)then return val end
end;
customEventHandler = function(self, event, ...)
if(bimg~=nil)and(textureMode=="stretch")and(event=="basalt_resize")then
texture = images.resizeBIMG(bimg, self:getSize())[textureId]
self:updateDraw()
end
local val = eventSystem:sendEvent("custom_event", self, event, ...)
if(val~=nil)then return val end
return true
end;
@@ -858,10 +1061,11 @@ return function(name)
initialized = true
return true
end
return false
end
}
object.__index = object
return object
end
end

View File

@@ -1,10 +1,17 @@
local curDir = fs.getDir(table.pack(...)[2]) or ""
local defaultPath = package.path
local format = "%s;/%s/?.lua;/%s/?/init.lua"
package.path = string.format(format, package.path, curDir,curDir)..string.format(format, package.path, curDir.."/libraries",curDir.."/libraries")..string.format(format, package.path, curDir.."/objects",curDir.."/objects")
if not(packed)then
local format = "path;/path/?.lua;/path/?/init.lua;"
local main = format:gsub("path", curDir)
local objFolder = format:gsub("path", curDir.."/objects")
local libFolder = format:gsub("path", curDir.."/libraries")
package.path = main..objFolder..libFolder..defaultPath
end
local Basalt = require("main")
package.path = defaultPath
return Basalt
return Basalt

View File

@@ -126,6 +126,52 @@ return function(drawTerm)
end
end
local function blit(x, y, t, fg, bg)
if(#t == #fg)or(#t == #bg)then
if (y >= 1) and (y <= height) then
if (x + t:len() > 0) and (x <= width) then
local oldCacheT = cacheT[y]
local oldCacheFG = cacheFG[y]
local oldCacheBG = cacheBG[y]
local newCacheT, newCacheFG, newCacheBG
local nEnd = x + #t - 1
if (x < 1) then
local startN = 1 - x + 1
local endN = width - x + 1
t = sub(t, startN, endN)
fg = sub(fg, startN, endN)
bg = sub(bg, startN, endN)
elseif (nEnd > width) then
local endN = width - x + 1
t = sub(t, 1, endN)
fg = sub(fg, 1, endN)
bg = sub(bg, 1, endN)
end
if (x > 1) then
local endN = x - 1
newCacheT = sub(oldCacheT, 1, endN) .. t
newCacheFG = sub(oldCacheFG, 1, endN) .. fg
newCacheBG = sub(oldCacheBG, 1, endN) .. bg
else
newCacheT = t
newCacheFG = fg
newCacheBG = bg
end
if nEnd < width then
newCacheT = newCacheT .. sub(oldCacheT, nEnd + 1, width)
newCacheFG = newCacheFG .. sub(oldCacheFG, nEnd + 1, width)
newCacheBG = newCacheBG .. sub(oldCacheBG, nEnd + 1, width)
end
cacheT[y] = newCacheT
cacheFG[y] = newCacheFG
cacheBG[y] = newCacheBG
end
end
end
end
local drawHelper = {
setSize = function(w, h)
width, height = w, h
@@ -147,6 +193,10 @@ return function(drawTerm)
setFG(x, y, colorStr)
end;
blit = function(x, y, t, fg, bg)
blit(x, y, t, fg, bg)
end,
drawBackgroundBox = function(x, y, width, height, bgCol)
for n = 1, height do
setBG(x, y + (n - 1), rep(tHex[bgCol], width))

381
Basalt/libraries/bimg.lua Normal file
View File

@@ -0,0 +1,381 @@
local sub,rep = string.sub,string.rep
local function frame(base, manager)
local w, h = 0, 0
local t,fg,bg = {}, {}, {}
local x, y = 1,1
local data = {}
local function recalculateSize()
for y=1,h do
if(t[y]==nil)then
t[y] = rep(" ", w)
else
t[y] = t[y]..rep(" ", w-#t[y])
end
if(fg[y]==nil)then
fg[y] = rep("0", w)
else
fg[y] = fg[y]..rep("0", w-#fg[y])
end
if(bg[y]==nil)then
bg[y] = rep("f", w)
else
bg[y] = bg[y]..rep("f", w-#bg[y])
end
end
end
local addText = function(text, _x, _y)
x = _x or x
y = _y or y
if(t[y]==nil)then
t[y] = rep(" ", x-1)..text..rep(" ", w-(#text+x))
else
t[y] = sub(t[y], 1, x-1)..rep(" ", x-#t[y])..text..sub(t[y], x+#text, w)
end
if(#t[y]>w)then w = #t[y] end
if(y > h)then h = y end
manager.updateSize(w, h)
end
local addBg = function(b, _x, _y)
x = _x or x
y = _y or y
if(bg[y]==nil)then
bg[y] = rep("f", x-1)..b..rep("f", w-(#b+x))
else
bg[y] = sub(bg[y], 1, x-1)..rep("f", x-#bg[y])..b..sub(bg[y], x+#b, w)
end
if(#bg[y]>w)then w = #bg[y] end
if(y > h)then h = y end
manager.updateSize(w, h)
end
local addFg = function(f, _x, _y)
x = _x or x
y = _y or y
if(fg[y]==nil)then
fg[y] = rep("0", x-1)..f..rep("0", w-(#f+x))
else
fg[y] = sub(fg[y], 1, x-1)..rep("0", x-#fg[y])..f..sub(fg[y], x+#f, w)
end
if(#fg[y]>w)then w = #fg[y] end
if(y > h)then h = y end
manager.updateSize(w, h)
end
local function setFrame(frm)
data = {}
t, fg, bg = {}, {}, {}
for k,v in pairs(base)do
if(type(k)=="string")then
data[k] = v
else
t[k], fg[k], bg[k] = v[1], v[2], v[3]
end
end
manager.updateSize(w, h)
end
if(base~=nil)then
w = #base[1][1]
h = #base
setFrame(base)
end
return {
recalculateSize = recalculateSize,
setFrame = setFrame,
getFrame = function()
local f = {}
for k,v in pairs(t)do
table.insert(f, {v, fg[k], bg[k]})
end
for k,v in pairs(data)do
f[k] = v
end
return f, w, h
end,
getImage = function()
local i = {}
for k,v in pairs(t)do
table.insert(i, {v, fg[k], bg[k]})
end
return i
end,
setFrameData = function(key, value)
if(value~=nil)then
data[key] = value
else
if(type(key)=="table")then
data = key
end
end
end,
setFrameImage = function(imgData)
for k,v in pairs(imgData.t)do
t[k] = imgData.t[k]
fg[k] = imgData.fg[k]
bg[k] = imgData.bg[k]
end
end,
getFrameImage = function()
return {t = t, fg = fg, bg = bg}
end,
getFrameData = function(key)
return (key~= nil and data[key] or data)
end,
blit = function(text, fgCol, bgCol, x, y)
addText(text, x, y)
addFg(fgCol, x, y)
addBg(bgCol, x, y)
end,
text = addText,
fg = addFg,
bg = addBg,
getSize = function()
return w, h
end,
setSize = function(_w, _h)
local nt,nfg,nbg = {}, {}, {}
for _y=1,_h do
if(t[_y]~=nil)then
nt[_y] = sub(t[_y], 1, _w)..rep(" ", _w - w)
else
nt[_y] = rep(" ", _w)
end
if(fg[_y]~=nil)then
nfg[_y] = sub(fg[_y], 1, _w)..rep("0", _w - w)
else
nfg[_y] = rep("0", _w)
end
if(bg[_y]~=nil)then
nbg[_y] = sub(bg[_y], 1, _w)..rep("f", _w - w)
else
nbg[_y] = rep("f", _w)
end
end
t, fg, bg = nt, nfg, nbg
w, h = _w, _h
end,
}
end
return function(img)
local frames = {}
local metadata = {creator="Bimg Library by NyoriE", date=os.date("!%Y-%m-%dT%TZ")}
local width,height = 0, 0
local manager = {}
local function addFrame(id, data)
id = id or #frames+1
table.insert(frames, id, frame(data, manager))
if(data==nil)then
frames[id].setSize(width, height)
end
end
local function removeFrame(id)
table.remove(frames, id or #frames)
end
local function moveFrame(id, dir)
local f = frames[id]
if(f~=nil)then
local newId = id+dir
if(newId>=1)and(newId<=#frames)then
table.remove(frames, id)
table.insert(frames, newId, f)
end
end
end
manager = {
updateSize = function(w, h, force)
local changed = force==true and true or false
if(w > width)then changed = true width = w end
if(h > height)then changed = true height = h end
if(changed)then
for k,v in pairs(frames)do
v.setSize(width, height)
v.recalculateSize()
end
end
end,
text = function(frame, text, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.text(text, x, y)
end,
fg = function(frame, fg, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.fg(fg, x, y)
end,
bg = function(frame, bg, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.bg(bg, x, y)
end,
blit = function(frame, text, fg, bg, x, y)
local f = frames[frame]
if(f==nil)then
f = addFrame(frame)
end
f.blit(text, fg, bg, x, y)
end,
setSize = function(w, h)
width = w
height = h
for k,v in pairs(frames)do
v.setSize(w, h)
end
end,
getFrame = function(id)
if(frames[id]~=nil)then
return frames[id].getFrame()
end
end,
getFrameObjects = function()
return frames
end,
getFrames = function()
local f = {}
for k,v in pairs(frames)do
local frame = v.getFrame()
table.insert(f, frame)
end
return f
end,
getFrameObject = function(id)
return frames[id]
end,
addFrame = function(id)
local f = frame()
if(#frames<=1)then
if(metadata.animated==nil)then
metadata.animated = true
end
if(metadata.secondsPerFrame==nil)then
metadata.secondsPerFrame = 0.2
end
end
addFrame(id)
return f
end,
removeFrame = function(id)
removeFrame(id)
if(#frames<=1)then
if(metadata.animated==nil)then
metadata.animated = true
end
if(metadata.secondsPerFrame==nil)then
metadata.secondsPerFrame = 0.2
end
end
end,
moveFrame = moveFrame,
setFrameData = function(id, key, value)
if(frames[id]~=nil)then
frames[id].setFrameData(key, value)
end
end,
getFrameData = function(id, key)
return frames[id]~=nil and frames[id].getFrameData(key)
end,
getSize = function()
return width, height
end,
setAnimation = function(anim)
metadata.animation = anim
end,
setMetadata = function(key, val)
if(val~=nil)then
metadata[key] = val
else
if(type(key)=="table")then
metadata = key
end
end
end,
getMetadata = function(key)
return key~=nil and metadata[key] or metadata
end,
createBimg = function()
local bimg = {}
for k,v in pairs(frames)do
local f = v.getFrame()
table.insert(bimg, f)
end
for k,v in pairs(metadata)do
bimg[k] = v
end
bimg.width = width
bimg.height = height
return bimg
end,
}
if(img~=nil)then
for k,v in pairs(img)do
if(type(k)=="string")then
metadata[k] = v
else
addFrame(k, v)
end
end
if(metadata.width==nil)or(metadata.height==nil)then
for k,v in pairs(frames)do
local w, h = v.getSize()
if(w>width)then w = width end
if(h>height)then h = height end
end
manager.updateSize(width, height, true)
end
else
addFrame(1)
end
return manager
end

View File

@@ -1,197 +0,0 @@
local function line(x1,y1,x2,y2)
local points = {}
if x1 == x2 and y1 == y2 then return {x=x1,y=x2} end
local minX = math.min(x1, x2)
local maxX, minY, maxY
if minX == x1 then minY,maxX,maxY = y1,x2,y2
else minY,maxX,maxY = y2,x1,y1 end
local xDiff,yDiff = maxX - minX,maxY - minY
if xDiff > math.abs(yDiff) then
local y = minY
local dy = yDiff / xDiff
for x = minX, maxX do
table.insert(points,{x=x,y=math.floor(y + 0.5)})
y = y + dy
end
else
local x,dx = minX,xDiff / yDiff
if maxY >= minY then
for y = minY, maxY do
table.insert(points,{x=math.floor(x + 0.5),y=y})
x = x + dx
end
else
for y = minY, maxY, -1 do
table.insert(points,{x=math.floor(x + 0.5),y=y})
x = x - dx
end
end
end
return points
end
local function filledCircle(xC, yC, r)
local points = {}
for x=-r, r+1 do
local dy = math.floor(math.sqrt(r*r - x*x))
for y=-dy, dy+1 do
table.insert(points, {x=xC+x, y=yC+y})
end
end
return points
end
local function ellipse(xC, yC, r1, r2, filled)
local rx,ry = math.ceil(math.floor(r1-0.5)/2),math.ceil(math.floor(r2-0.5)/2)
local x,y=0,ry
local d1 = ((ry * ry) - (rx * rx * ry) + (0.25 * rx * rx))
local dx = 2*ry^2*x
local dy = 2*rx^2*y
local points = {}
while dx < dy do
table.insert(points,{x=x+xC,y=y+yC})
table.insert(points,{x=-x+xC,y=y+yC})
table.insert(points,{x=x+xC,y=-y+yC})
table.insert(points,{x=-x+xC,y=-y+yC})
if filled then
for y=-y+yC+1,y+yC-1 do
table.insert(points,{x=x+xC,y=y})
table.insert(points,{x=-x+xC,y=y})
end
end
if d1 < 0 then
x = x + 1
dx = dx + 2*ry^2
d1 = d1 + dx + ry^2
else
x,y = x+1,y-1
dx = dx + 2*ry^2
dy = dy - 2*rx^2
d1 = d1 + dx - dy + ry^2
end
end
local d2 = (((ry * ry) * ((x + 0.5) * (x + 0.5))) + ((rx * rx) * ((y - 1) * (y - 1))) - (rx * rx * ry * ry))
while y >= 0 do
table.insert(points,{x=x+xC,y=y+yC})
table.insert(points,{x=-x+xC,y=y+yC})
table.insert(points,{x=x+xC,y=-y+yC})
table.insert(points,{x=-x+xC,y=-y+yC})
if filled then
for y=-y+yC,y+yC do
table.insert(points,{x=x+xC,y=y})
table.insert(points,{x=-x+xC,y=y})
end
end
if d2 > 0 then
y = y - 1
dy = dy - 2*rx^2
d2 = d2 + rx^2 - dy
else
y = y - 1
x = x + 1
dy = dy - 2*rx^2
dx = dx + 2*ry^2
d2 = d2 + dx - dy + rx^2
end
end
return points
end
local function circle(xC, yC, r, filled)
return ellipse(xC, yC, r, r, filled)
end
return {
circle = function(x, y, radius, filled)
return circle(x, y, radius, filled)
end,
rectangle = function(x1, y1, x2, y2, filled)
local points = {}
if(filled)then
for y=y1,y2 do
for x=x1,x2 do
table.insert(points, {x=x,y=y})
end
end
else
for y=y1,y2 do
for x=x1,x2 do
if(x==x1)or(x==x2)or(y==y1)or(y==y2)then
table.insert(points, {x=x,y=y})
end
end
end
end
return points
end,
triangle = function(x1, y1, x2, y2, x3, y3, filled)
local function drawFlatTopTriangle(points,x1,y1,x2,y2,x3,y3)
local m1 = (x3 - x1) / (y3 - y1)
local m2 = (x3 - x2) / (y3 - y2)
local yStart = math.ceil(y1 - 0.5)
local yEnd = math.ceil(y3 - 0.5)-1
for y = yStart, yEnd do
local px1 = m1 * (y + 0.5 - y1) + x1
local px2 = m2 * (y + 0.5 - y2) + x2
local xStart = math.ceil(px1 - 0.5)
local xEnd = math.ceil(px2 - 0.5)
for x=xStart,xEnd do
table.insert(points,{x=x,y=y})
end
end
end
local function drawFlatBottomTriangle(points,x1,y1,x2,y2,x3,y3)
local m1 = (x2 - x1) / (y2 - y1)
local m2 = (x3 - x1) / (y3 - y1)
local yStart = math.ceil(y1-0.5)
local yEnd = math.ceil(y3-0.5)-1
for y = yStart, yEnd do
local px1 = m1 * (y + 0.5 - y1) + x1
local px2 = m2 * (y + 0.5 - y1) + x1
local xStart = math.ceil(px1 - 0.5)
local xEnd = math.ceil(px2 - 0.5)
for x=xStart,xEnd do
table.insert(points,{x=x,y=y})
end
end
end
local points = {}
if(filled)then
if y2 < y1 then x1,y1,x2,y2 = x2,y2,x1,y1 end
if y3 < y2 then x2,y2,x3,y3 = x3,y3,x2,y2 end
if y2 < y2 then x1,y1,x2,y2 = x2,y2,x1,y1 end
if y1 == y2 then
if x2 < x1 then x1,y1,x2,y2 = x2,y2,x1,y1 end
drawFlatTopTriangle(points,x1,y1,x2,y2,x3,y3)
elseif y2 == y3 then
if x3 < x2 then x3,y3,x2,y2 = x2,y2,x3,y3 end
drawFlatBottomTriangle(points,x1,y1,x2,y2,x3,y3)
else
local alphaSplit = (y2-y1)/(y3-y1)
local x = x1 + ((x3 - x1) * alphaSplit)
local y = y1 + ((y3 - y1) * alphaSplit)
if x2 < x then
drawFlatBottomTriangle(points,x1,y1,x2,y2,x, y)
drawFlatTopTriangle(points,x2,y2,x,y,x3,y3)
else
drawFlatBottomTriangle(points,x1,y1,x,y,x1,y1)
drawFlatTopTriangle(points,x,y,x2,y2,x3,y3)
end
end
else
points = line(x1,y1,x2,y2)
for k,v in pairs(line(x2,y2,x3,y3))do table.insert(points, v) end
for k,v in pairs(line(x3,y3,x1,y1))do table.insert(points, v) end
end
return points
end,
line = line,
ellipse = function(xCenter, yCenter, radius1, radius2, filled)
return ellipse(xCenter, yCenter, radius1, radius2, filled)
end
}

View File

@@ -0,0 +1,97 @@
local sub,floor,rep = string.sub,math.floor,string.rep
local function loadNFPAsBimg(path)
local bimg = {{}}
local nfp = fs.open(path, "r")
if(nfp~=nil)then
for line in nfp.readLine do
table.insert(bimg[1], {rep(" ",#line), rep(" ",#line), line})
end
nfp.close()
return bimg
end
end
local function loadNFP(path)
return paintutils.loadImage(path), "nfp"
end
local function loadBIMG(path)
local f = fs.open(path, "rb")
local content = textutils.unserialize(f.readAll())
f.close()
if(content~=nil)then
return content, "bimg"
end
end
local function loadBBF(path)
end
local function loadBBFAsBimg(path)
end
local function loadImage(path, f)
if(f==nil)then
if(path:find(".bimg"))then
return loadBIMG(path)
elseif(path:find(".bbf"))then
return loadBBF(path)
else
return loadNFP(path)
end
end
-- ...
end
local function loadImageAsBimg(path, f)
if(f==nil)then
if(path:find(".bimg"))then
return loadBIMG(path)
elseif(path:find(".bbf"))then
return loadBBFAsBimg(path)
else
return loadNFPAsBimg(path)
end
end
end
local function resizeBIMG(source, w, h)
local oW, oH = source.width or #source[1][1][1], source.height or #source[1]
local newImg = {}
for k,v in pairs(source)do
if(type(k)=="number")then
local frame = {}
for y=1, h do
local xT,xFG,xBG = "","",""
local yR = floor(y / h * oH + 0.5)
if(v[yR]~=nil)then
for x=1, w do
local xR = floor(x / w * oW + 0.5)
xT = xT..sub(v[yR][1], xR,xR)
xFG = xFG..sub(v[yR][2], xR,xR)
xBG = xBG..sub(v[yR][3], xR,xR)
end
table.insert(frame, {xT, xFG, xBG})
end
end
table.insert(newImg, k, frame)
else
newImg[k] = v
end
end
newImg.width = w
newImg.height = h
return newImg
end
return {
loadNFP = loadNFP,
loadBIMG = loadBIMG,
loadImage = loadImage,
resizeBIMG = resizeBIMG,
loadImageAsBimg = loadImageAsBimg,
}

View File

@@ -0,0 +1,4 @@
return function(path)
local exists, content = pcall(require, path)
return exists and content or nil
end

View File

@@ -2,14 +2,31 @@ local processes = {}
local process = {}
local processId = 0
function process:new(path, window, ...)
local newPackage = dofile("rom/modules/main/cc/require.lua").make
function process:new(path, window, newEnv, ...)
local args = {...}
local newP = setmetatable({ path = path }, { __index = self })
newP.window = window
window.current = term.current
window.redirect = term.redirect
newP.processId = processId
if(type(path)=="string")then
newP.coroutine = coroutine.create(function()
shell.execute(path, table.unpack(args))
local pPath = shell.resolveProgram(path)
local env = setmetatable(newEnv, {__index=_ENV})
env.shell = shell
env.basaltProgram=true
env.require, env.package = newPackage(env, fs.getDir(pPath))
if(fs.exists(pPath))then
local file = fs.open(pPath, "r")
local content = file.readAll()
file.close()
local program = load(content, path, "bt", env)
if(program~=nil)then
return program(table.unpack(args))
end
end
end)
elseif(type(path)=="function")then
newP.coroutine = coroutine.create(function()
@@ -24,17 +41,21 @@ function process:new(path, window, ...)
end
function process:resume(event, ...)
local cur = term.current()
term.redirect(self.window)
if(self.filter~=nil)then
if(event~=self.filter)then return end
self.filter=nil
end
local ok, result = coroutine.resume(self.coroutine, event, ...)
if ok then
self.filter = result
else
error(result)
printError(result)
end
term.redirect(cur)
return ok, result
end
function process:isDead()
@@ -60,4 +81,4 @@ function process:start()
coroutine.resume(self.coroutine)
end
return process
return process

View File

@@ -1,17 +1,92 @@
local splitString = function(str, sep)
if sep == nil then
sep = "%s"
local sub,find,reverse = string.sub,string.find,string.reverse
local function splitString(str, delimiter)
local result = {}
if str == "" or delimiter == "" then
return result
end
local start = 1
local delim_start, delim_end = find(str, delimiter, start)
while delim_start do
table.insert(result, sub(str, start, delim_start - 1))
start = delim_end + 1
delim_start, delim_end = find(str, delimiter, start)
end
local t={}
for v in string.gmatch(str, "([^"..sep.."]+)") do
table.insert(t, v)
end
return t
table.insert(result, sub(str, start))
return result
end
local relations = {[0] = {8, 4, 3, 6, 5}, {4, 14, 8, 7}, {6, 10, 8, 7}, {9, 11, 8, 0}, {1, 14, 8, 0}, {13, 12, 8, 0}, {2, 10, 8, 0}, {15, 8, 10, 11, 12, 14},
{0, 7, 1, 9, 2, 13}, {3, 11, 8, 7}, {2, 6, 7, 15}, {9, 3, 7, 15}, {13, 5, 7, 15}, {5, 12, 8, 7}, {1, 4, 7, 15}, {7, 10, 11, 12, 14}}
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do exponents[2^i] = i end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do thisRel[i] = 2 ^ thisRel[i] end
end
end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do
local thisRelation = lastCol[j]
for i = 1, #usage - 1 do if usage[i][1] == thisRelation then return i end end
end
return 1
end
local function colsToChar(pattern, totals)
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do usage[#usage + 1] = {key, value} end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function (a, b) return a[2] > b[2] end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do if pattern[i] ~= pattern[6] then data = data + 2^(i-1) end end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else
-- Solid colour character:
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
end
end
return {
getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
text = string.sub(text, 1, width)
text = sub(text, 1, width)
local offset = width - string.len(text)
if (textAlign == "right") then
text = string.rep(replaceChar or " ", offset) .. text
@@ -62,22 +137,25 @@ splitString = splitString,
createText = function(str, width)
local uniqueLines = splitString(str, "\n")
local lines = {}
local result = {}
for k,v in pairs(uniqueLines)do
local line = ""
local words = splitString(v, " ")
for a,b in pairs(words)do
if(#line+#b <= width)then
line = line=="" and b or line.." "..b
if(a==#words)then table.insert(lines, line) end
if(#v==0)then table.insert(result, "") end
while #v > width do
local last_space = find(reverse(sub(v, 1, width)), " ")
if not last_space then
last_space = width
else
table.insert(lines, line)
line = b:sub(1,width)
if(a==#words)then table.insert(lines, line) end
last_space = width - last_space + 1
end
local line = sub(v, 1, last_space)
table.insert(result, line)
v = sub(v, last_space + 1)
end
if #v > 0 then
table.insert(result, v)
end
end
return lines
return result
end,
getValueFromXML = function(name, tab)
@@ -117,4 +195,36 @@ uuid = function()
end
return uuid()
end,
array = function(arraysize, hashsize)
return load("return {" .. ("nil,"):rep(arraysize) .. ("[0]=nil,"):rep(hashsize) .. "}")()
end,
shrink = function(image, bgCol)
local results, width, height, bgCol = {{}, {}, {}}, 0, #image + #image % 3, bgCol or colours.black
for i = 1, #image do if #image[i] > width then width = #image[i] end end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do for xx = 1, 2 do
pattern[#pattern + 1] = (image[y + yy] and image[y + yy][x + xx]) and (image[y + yy][x + xx] == 0 and bgCol or image[y + yy][x + xx]) or bgCol
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
end end
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
counter = counter + 1
end
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
end
results.width, results.height = #results[1][1], #results[1]
return results
end,
}

View File

@@ -6,11 +6,11 @@ local log = require("basaltLogs")
local uuid = utils.uuid
local createText = utils.createText
local count = utils.tableCount
local moveThrottle = 300
local dragThrottle = 50
local baseTerm = term.current()
local version = "1.6.2"
local debugger = true
local version = "1.6.4"
local projectDirectory = fs.getDir(table.pack(...)[2] or "")
@@ -23,10 +23,56 @@ if not term.isColor or not term.isColor() then
error('Basalt requires an advanced (golden) computer to run.', 0)
end
local defaultColors = {}
for k,v in pairs(colors)do
if(type(v)=="number")then
defaultColors[k] = {baseTerm.getPaletteColor(v)}
end
end
local function stop()
updaterActive = false
baseTerm.clear()
baseTerm.setCursorPos(1, 1)
for k,v in pairs(colors)do
if(type(v)=="number")then
baseTerm.setPaletteColor(v, colors.packRGB(table.unpack(defaultColors[k])))
end
end
end
local function basaltError(errMsg)
baseTerm.clear()
baseTerm.setBackgroundColor(colors.black)
baseTerm.setTextColor(colors.red)
local w,h = baseTerm.getSize()
if(basalt.logging)then
log(errMsg, "Error")
end
local text = createText("Basalt error: "..errMsg, w)
local yPos = 1
for k,v in pairs(text)do
baseTerm.setCursorPos(1,yPos)
baseTerm.write(v)
yPos = yPos + 1
end
baseTerm.setCursorPos(1,yPos+1)
updaterActive = false
end
local function schedule(f)
assert(f~="function", "Schedule needs a function in order to work!")
return function(...)
local co = coroutine.create(f)
local ok, result = coroutine.resume(co, ...)
if(ok)then
table.insert(schedules, {co, result})
else
basaltError(result)
end
end
end
local setVariable = function(name, var)
@@ -46,6 +92,10 @@ local getTheme = function(name)
end
local bInstance = {
getDynamicValueEventSetting = function()
return basalt.dynamicValueEvents
end,
getMainFrame = function()
return mainFrame
end,
@@ -94,6 +144,8 @@ local bInstance = {
return baseTerm
end,
schedule = schedule,
stop = stop,
newFrame = Frame,
@@ -102,35 +154,26 @@ local bInstance = {
end
}
local basaltError = function(errMsg)
baseTerm.clear()
baseTerm.setBackgroundColor(colors.black)
baseTerm.setTextColor(colors.red)
local w,h = baseTerm.getSize()
if(basalt.logging)then
log(errMsg, "Error")
end
local text = createText("Basalt error: "..errMsg, w)
local yPos = 1
for k,v in pairs(text)do
baseTerm.setCursorPos(1,yPos)
baseTerm.write(v)
yPos = yPos + 1
end
baseTerm.setCursorPos(1,yPos+1)
updaterActive = false
end
local function handleSchedules(event, p1, p2, p3, p4)
local function handleSchedules(event, ...)
if(#schedules>0)then
local finished = {}
for n=1,#schedules do
if(schedules[n]~=nil)then
if (coroutine.status(schedules[n]) == "suspended")then
local ok, result = coroutine.resume(schedules[n], event, p1, p2, p3, p4)
if not(ok)then
basaltError(result)
if (coroutine.status(schedules[n][1]) == "suspended")then
if(schedules[n][2]~=nil)then
if(schedules[n][2]==event)then
local ok, result = coroutine.resume(schedules[n][1], event, ...)
schedules[n][2] = result
if not(ok)then
basaltError(result)
end
end
else
local ok, result = coroutine.resume(schedules[n][1], event, ...)
schedules[n][2] = result
if not(ok)then
basaltError(result)
end
end
else
table.insert(finished, n)
@@ -159,71 +202,112 @@ local function drawFrames()
end
end
local function basaltUpdateEvent(event, p1, p2, p3, p4)
if(basaltEvent:sendEvent("basaltEventCycle", event, p1, p2, p3, p4)==false)then return end
if(mainFrame~=nil)then
if (event == "mouse_click") then
mainFrame:mouseHandler(p1, p2, p3, false)
activeFrame = mainFrame
elseif (event == "mouse_drag") then
mainFrame:dragHandler(p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "mouse_up") then
mainFrame:mouseUpHandler(p1, p2, p3, p4)
activeFrame = mainFrame
elseif (event == "mouse_scroll") then
mainFrame:scrollHandler(p1, p2, p3, p4)
activeFrame = mainFrame
local stopped, moveX, moveY = nil, nil, nil
local moveTimer = nil
local function mouseMoveEvent(_, stp, x, y)
stopped, moveX, moveY = stp, x, y
if(moveTimer==nil)then
moveTimer = os.startTimer(moveThrottle/1000)
end
end
local function moveHandlerTimer()
moveTimer = nil
mainFrame:hoverHandler(moveX, moveY, stopped)
activeFrame = mainFrame
end
local btn, dragX, dragY = nil, nil, nil
local dragTimer = nil
local function dragHandlerTimer()
dragTimer = nil
mainFrame:dragHandler(btn, dragX, dragY)
activeFrame = mainFrame
end
local function mouseDragEvent(_, b, x, y)
btn, dragX, dragY = b, x, y
if(dragThrottle<50)then
dragHandlerTimer()
else
if(dragTimer==nil)then
dragTimer = os.startTimer(dragThrottle/1000)
end
end
end
local function basaltUpdateEvent(event, ...)
local a = {...}
if(basaltEvent:sendEvent("basaltEventCycle", event, ...)==false)then return end
if(event=="terminate")then basalt.stop() end
if(mainFrame~=nil)then
local mouseEvents = {
mouse_click = mainFrame.mouseHandler,
mouse_up = mainFrame.mouseUpHandler,
mouse_scroll = mainFrame.scrollHandler,
mouse_drag = mouseDragEvent,
mouse_move = mouseMoveEvent,
}
local mouseEvent = mouseEvents[event]
if(mouseEvent~=nil)then
mouseEvent(mainFrame, ...)
handleSchedules(event, ...)
drawFrames()
return
end
end
if(event == "monitor_touch") then
if(monFrames[p1]~=nil)then
monFrames[p1]:mouseHandler(1, p2, p3, true)
activeFrame = monFrames[p1]
if(monFrames[a[1]]~=nil)then
monFrames[a[1]]:mouseHandler(1, a[2], a[3], true)
activeFrame = monFrames[a[1]]
end
if(count(monGroups)>0)then
for k,v in pairs(monGroups)do
v[1]:mouseHandler(1, p2, p3, true, p1)
v[1]:mouseHandler(1, a[2], a[3], true, a[1])
end
end
handleSchedules(event, ...)
drawFrames()
return
end
if(activeFrame~=nil)then
local keyEvents = {
char = activeFrame.charHandler,
key = activeFrame.keyHandler,
key_up = activeFrame.keyUpHandler,
}
local keyEvent = keyEvents[event]
if(keyEvent~=nil)then
if(event == "key")then
activeKey[a[1]] = true
elseif(event == "key_up")then
activeKey[a[1]] = false
end
keyEvent(activeFrame, ...)
handleSchedules(event, ...)
drawFrames()
return
end
end
if(event == "char")then
if(activeFrame~=nil)then
activeFrame:charHandler(p1)
end
end
if(event == "key_up")then
if(activeFrame~=nil)then
activeFrame:keyUpHandler(p1)
end
activeKey[p1] = false
end
if(event == "key")then
if(activeFrame~=nil)then
activeFrame:keyHandler(p1, p2)
end
activeKey[p1] = true
end
if(event == "terminate")then
if(activeFrame~=nil)then
activeFrame:eventHandler(event)
if(updaterActive==false)then return end
end
end
if(event~="mouse_click")and(event~="mouse_up")and(event~="mouse_scroll")and(event~="mouse_drag")and(event~="key")and(event~="key_up")and(event~="char")and(event~="terminate")then
if(event=="timer")and(a[1]==moveTimer)then
moveHandlerTimer()
elseif(event=="timer")and(a[1]==dragTimer)then
dragHandlerTimer()
else
for k, v in pairs(frames) do
v:eventHandler(event, p1, p2, p3, p4)
v:eventHandler(event, ...)
end
end
handleSchedules(event, p1, p2, p3, p4)
handleSchedules(event, ...)
drawFrames()
end
basalt = {
logging = false,
dynamicValueEvents = false,
setTheme = setTheme,
getTheme = getTheme,
drawFrames = drawFrames,
@@ -242,6 +326,28 @@ basalt = {
log(...)
end,
setMouseMoveThrottle = function(amount)
if(_HOST:find("CraftOS%-PC"))then
if(config.get("mouse_move_throttle")~=10)then config.set("mouse_move_throttle", 10) end
if(amount<100)then
moveThrottle = 100
else
moveThrottle = amount
end
return true
end
return false
end,
setMouseDragThrottle = function(amount)
if(amount<=0)then
dragThrottle = 0
else
dragTimer = nil
dragThrottle = amount
end
end,
autoUpdate = function(isActive)
updaterActive = isActive
if(isActive==nil)then updaterActive = true end
@@ -258,9 +364,9 @@ basalt = {
end
end,
update = function(event, p1, p2, p3, p4)
update = function(event, ...)
if (event ~= nil) then
local ok, err = xpcall(basaltUpdateEvent, debug.traceback, event, p1, p2, p3, p4)
local ok, err = xpcall(basaltUpdateEvent, debug.traceback, event, ...)
if not(ok)then
basaltError(err)
return
@@ -304,18 +410,7 @@ basalt = {
end
end,
schedule = function(f)
assert(f~="function", "Schedule needs a function in order to work!")
return function(...)
local co = coroutine.create(f)
local ok, result = coroutine.resume(co, ...)
if(ok)then
table.insert(schedules, co)
else
basaltError(result)
end
end
end,
schedule = schedule,
createFrame = function(name)
name = name or uuid()
@@ -341,6 +436,10 @@ basalt = {
projectDirectory = dir
end,
forceRenderUpdate = function()
drawFrames()
end,
debug = function(...)
local args = { ... }
if(mainFrame==nil)then print(...) return end

4
Basalt/module.lua Normal file
View File

@@ -0,0 +1,4 @@
return function(path)
local exists, content = pcall(require, path)
return exists and content or nil
end

View File

@@ -1,7 +1,9 @@
local xmlValue = require("utils").getValueFromXML
local basaltEvent = require("basaltEvent")
local floor,sin,cos,pi = math.floor,math.sin,math.cos,math.pi
local floor,sin,cos,pi,sqrt,pow = math.floor,math.sin,math.cos,math.pi,math.sqrt,math.pow
-- You can find the easing curves here https://easings.net
local lerp = function(s, e, pct)
return s + (e - s) * pct
@@ -39,16 +41,183 @@ local easeInOutSine = function(t)
return -(cos(pi * x) - 1) / 2
end
local easeInBack = function(t)
local c1 = 1.70158;
local c3 = c1 + 1
return c3*t^3-c1*t^2
end
local easeInCubic = function(t)
return t^3
end
local easeInElastic = function(t)
local c4 = (2*pi)/3;
return t == 0 and 0 or (t == 1 and 1 or (
-2^(10*t-10)*sin((t*10-10.75)*c4)
))
end
local function easeInExpo(t)
return t == 0 and 0 or 2^(10*t-10)
end
local function easeInExpo(t)
return t == 0 and 0 or 2^(10*t-10)
end
local function easeInOutBack(t)
local c1 = 1.70158;
local c2 = c1 * 1.525;
return t < 0.5 and ((2*t)^2*((c2+1)*2*t-c2))/2 or ((2*t-2)^2*((c2+1)*(t*2-2)+c2)+2)/2
end
local function easeInOutCubic(t)
return t < 0.5 and 4 * t^3 or 1-(-2*t+2)^3 / 2
end
local function easeInOutElastic(t)
local c5 = (2*pi) / 4.5
return t==0 and 0 or (t == 1 and 1 or (t < 0.5 and -(2^(20*t-10) * sin((20*t - 11.125) * c5))/2 or (2^(-20*t+10) * sin((20*t - 11.125) * c5))/2 + 1))
end
local function easeInOutExpo(t)
return t == 0 and 0 or (t == 1 and 1 or (t < 0.5 and 2^(20*t-10)/2 or (2-2^(-20*t+10)) /2))
end
local function easeInOutQuad(t)
return t < 0.5 and 2*t^2 or 1-(-2*t+2)^2/2
end
local function easeInOutQuart(t)
return t < 0.5 and 8*t^4 or 1 - (-2*t+2)^4 / 2
end
local function easeInOutQuint(t)
return t < 0.5 and 16*t^5 or 1-(-2*t+2)^5 / 2
end
local function easeInQuad(t)
return t^2
end
local function easeInQuart(t)
return t^4
end
local function easeInQuint(t)
return t^5
end
local function easeOutBack(t)
local c1 = 1.70158;
local c3 = c1 + 1
return 1+c3*(t-1)^3+c1*(t-1)^2
end
local function easeOutCubic(t)
return 1 - (1-t)^3
end
local function easeOutElastic(t)
local c4 = (2*pi)/3;
return t == 0 and 0 or (t == 1 and 1 or (2^(-10*t)*sin((t*10-0.75)*c4)+1))
end
local function easeOutExpo(t)
return t == 1 and 1 or 1-2^(-10*t)
end
local function easeOutQuad(t)
return 1 - (1 - t) * (1 - t)
end
local function easeOutQuart(t)
return 1 - (1-t)^4
end
local function easeOutQuint(t)
return 1 - (1 - t)^5
end
local function easeInCirc(t)
return 1 - sqrt(1 - pow(t, 2))
end
local function easeOutCirc(t)
return sqrt(1 - pow(t - 1, 2))
end
local function easeInOutCirc(t)
return t < 0.5 and (1 - sqrt(1 - pow(2 * t, 2))) / 2 or (sqrt(1 - pow(-2 * t + 2, 2)) + 1) / 2;
end
local function easeOutBounce(t)
local n1 = 7.5625;
local d1 = 2.75;
if (t < 1 / d1)then
return n1 * t * t
elseif (t < 2 / d1)then
local a = t - 1.5 / d1
return n1 * a * a + 0.75;
elseif (t < 2.5 / d1)then
local a = t - 2.25 / d1
return n1 * a * a + 0.9375;
else
local a = t - 2.625 / d1
return n1 * a * a + 0.984375;
end
end
local function easeInBounce(t)
return 1 - easeOutBounce(1 - t)
end
local function easeInOutBounce(t)
return x < 0.5 and (1 - easeOutBounce(1 - 2 * t)) / 2 or (1 + easeOutBounce(2 * t - 1)) / 2;
end
local lerp = {
linear = linear,
lerp = lerp,
flip=flip,
easeIn=easeIn,
easeOut=easeOut,
easeInOut=easeInOut,
easeOutSine = easeOutSine,
easeInSine = easeInSine,
easeInBack=easeInBack,
easeInCubic=easeInCubic,
easeInElastic=easeInElastic,
easeInExpo=easeInExpo,
easeInQuad=easeInQuad,
easeInQuart=easeInQuart,
easeInQuint=easeInQuint,
easeInCirc=easeInCirc,
easeInBounce=easeInBounce,
easeOut=easeOut,
easeOutSine = easeOutSine,
easeOutBack=easeOutBack,
easeOutCubic=easeOutCubic,
easeOutElastic=easeOutElastic,
easeOutExpo=easeOutExpo,
easeOutQuad=easeOutQuad,
easeOutQuart=easeOutQuart,
easeOutQuint=easeOutQuint,
easeOutCirc=easeOutCirc,
easeOutBounce=easeOutBounce,
easeInOut=easeInOut,
easeInOutSine = easeInOutSine,
easeInOutBack=easeInOutBack,
easeInOutCubic=easeInOutCubic,
easeInOutElastic=easeInOutElastic,
easeInOutExpo=easeInOutExpo,
easeInOutQuad=easeInOutQuad,
easeInOutQuart=easeInOutQuart,
easeInOutQuint=easeInOutQuint,
easeInOutCirc=easeInOutCirc,
easeInOutBounce=easeInOutBounce,
}
local activeAnimations = {}
@@ -185,6 +354,11 @@ return function(name)
return self
end,
addMode = function(self, modeId, modeF)
lerp[modeId] = modeF
return self
end,
generateXMLEventFunction = function(self, func, val)
local createF = function(str)
if(str:sub(1,1)=="#")then
@@ -362,9 +536,9 @@ return function(name)
return self
end,
add = function(self, func, wait)
add = function(self, func, timer)
lastFunc = func
addAnimationPart((wait or nextWaitTimer) + (animations[#animations]~=nil and animations[#animations].t or 0), func)
addAnimationPart((timer or nextWaitTimer) + (animations[#animations]~=nil and animations[#animations].t or 0), func)
return self
end;

View File

@@ -17,8 +17,10 @@ return function(name)
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ButtonBG")
self.fgColor = self.parent:getTheme("ButtonText")
if(base.init(self))then
self.bgColor = self.parent:getTheme("ButtonBG")
self.fgColor = self.parent:getTheme("ButtonText")
end
end,
getType = function(self)
return objectType
@@ -36,7 +38,7 @@ return function(name)
end;
setText = function(self, text)
base:setValue(text)
base:setValue(tostring(text))
self:updateDraw()
return self
end;
@@ -58,8 +60,9 @@ return function(name)
for n = 1, h do
if (n == verticalAlign) then
self.parent:setText(obx, oby + (n - 1), utils.getTextHorizontalAlign(self:getValue(), w, textHorizontalAlign))
self.parent:setFG(obx, oby + (n - 1), utils.getTextHorizontalAlign(tHex[self.fgColor]:rep(self:getValue():len()), w, textHorizontalAlign))
local val = self:getValue()
self.parent:setText(obx + (w/2-val:len()/2), oby + (n - 1), utils.getTextHorizontalAlign(val, val:len(), textHorizontalAlign))
self.parent:setFG(obx + (w/2-val:len()/2), oby + (n - 1), utils.getTextHorizontalAlign(tHex[self.fgColor]:rep(val:len()), val:len(), textHorizontalAlign))
end
end
end

View File

@@ -72,10 +72,12 @@ return function(name)
end,
init = function(self)
base.init(self)
self.bgColor = self.parent:getTheme("CheckboxBG")
self.fgColor = self.parent:getTheme("CheckboxText")
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("CheckboxBG")
self.fgColor = self.parent:getTheme("CheckboxText")
end
end,
}

View File

@@ -84,7 +84,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -101,7 +101,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
@@ -109,7 +109,7 @@ return function(name)
setSelectedItem = function(self, bgCol, fgCol, active)
itemSelectedBG = bgCol or self.bgColor
itemSelectedFG = fgCol or self.fgColor
selectionColorActive = active
selectionColorActive = active~=nil and active
self:updateDraw()
return self
end;
@@ -120,7 +120,11 @@ return function(name)
return self
end,
mouseHandler = function(self, button, x, y)
getDropdownSize = function(self)
return dropdownW, dropdownH
end,
mouseHandler = function(self, button, x, y, touch)
if (isOpened) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
if(button==1)then
@@ -131,6 +135,9 @@ return function(name)
self:setValue(list[n + yOffset])
self:updateDraw()
local val = self:getEventSystem():sendEvent("mouse_click", self, "mouse_click", dir, x, y)
if(touch)then
self:mouseUpHandler(button, x, y)
end
if(val==false)then return val end
return true
end
@@ -225,14 +232,14 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("DropdownBG")
self.fgColor = self.parent:getTheme("DropdownText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
if(self.parent~=nil)then
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("DropdownBG")
self.fgColor = self.parent:getTheme("DropdownText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end
end,
}

View File

@@ -1,7 +1,8 @@
local Object = require("Object")
local geometric = require("geometricPoints")
local tHex = require("tHex")
local xmlValue = require("utils").getValueFromXML
local bimgLib = require("bimg")
local images = require("images")
local sub,len,max,min = string.sub,string.len,math.max,math.min
@@ -9,420 +10,181 @@ return function(name)
-- Graphic
local base = Object(name)
local objectType = "Graphic"
base:setZIndex(2)
local imgData = bimgLib()
local bimgFrame = imgData.getFrameObject(1)
local bimg
local selectedFrame = 1
base:setZIndex(5)
local graphicObjects = {}
local graphic = {}
local shrinkedGraphic = {}
local isGraphicShrinked = false
local xOffset, yOffset = 0, 0
local dragable = false
local xMouse,yMouse
local w, h = 40, 15
local canvasSizeChanged = false
local tColourLookup = {}
for n=1,16 do
tColourLookup[ string.byte( "0123456789abcdef",n,n ) ] = 2^(n-1)
end
local function stringToTable(str)
local t = {}
for i = 1, #str do
t[i] = str:sub(i, i)
end
return t
end
local function setBG(x, y, width, height, colorStr)
if (y >= 1) and (y <= height) then
if (x + len(colorStr) > 0) and (x <= width) then
local oldCache = graphic[y]
local newCache
local nEnd = x + #colorStr - 1
if (x < 1) then
colorStr = sub(colorStr, 1 - x + 1, width - x + 1)
elseif (nEnd > width) then
colorStr = sub(colorStr, 1, width - x + 1)
end
if (x > 1) then
newCache = sub(oldCache, 1, x - 1) .. colorStr
else
newCache = colorStr
end
if nEnd < width then
newCache = newCache .. sub(oldCache, nEnd + 1, width)
end
graphic[y] = newCache
end
end
end
local function redrawCanvasSize()
local w,h = w,h
if(isGraphicShrinked)then w = w*2 h = h*3 end
for y=1,h do
if(graphic[y]~=nil)then
if(w>graphic[y]:len())then
graphic[y] = graphic[y]..(tHex[base.bgColor]):rep(w-graphic[y]:len())
else
graphic[y] = graphic[y]:sub(1,w)
end
else
graphic[y] = (tHex[base.bgColor]):rep(w)
end
end
end
redrawCanvasSize()
local function shrink()
local function parseLine( tImageArg, sLine )
local tLine = {}
for x=1,sLine:len() do
tLine[x] = tColourLookup[ string.byte(sLine,x,x) ] or 0
end
table.insert( tImageArg, tLine )
end
function parseImage( sRawData )
if type( sRawData ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sRawData ) .. ")" )
end
local tImage = {}
for sLine in ( sRawData .. "\n" ):gmatch( "(.-)\n" ) do
parseLine( tImage, sLine )
end
return tImage
end
local rawImg = ""
for y=1,#graphic do
if(y==#graphic)then
rawImg = rawImg..graphic[y]
else
rawImg = rawImg..graphic[y].."\n"
end
end
local img = parseImage(rawImg)
-- shrinkSystem is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 },
{ 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } }
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do
exponents[2 ^ i] = i
end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do
thisRel[i] = 2 ^ thisRel[i]
end
end
end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do
local thisRelation = lastCol[j]
for i = 1, #usage - 1 do
if usage[i][1] == thisRelation then
return i
end
end
end
return 1
end
local function colsToChar(pattern, totals)
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do
usage[#usage + 1] = { key, value }
end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function(a, b)
return a[2] > b[2]
end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do
if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end
end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do
if pattern[i] ~= pattern[6] then
data = data + 2 ^ (i - 1)
end
end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else
-- Solid colour character:
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
end
end
local results, width, height, bgCol = { {}, {}, {} }, 0, #img + #img % 3, base.bgColor or colors.black
for i = 1, #img do
if #img[i] > width then
width = #img[i]
end
end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do
for xx = 1, 2 do
pattern[#pattern + 1] = (img[y + yy] and img[y + yy][x + xx]) and (img[y + yy][x + xx] == 0 and bgCol or img[y + yy][x + xx]) or bgCol
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
end
end
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
counter = counter + 1
end
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
end
results.width, results.height = #results[1][1], #results[1]
shrinkedGraphic = results
end
local function redraw()
local w,h = w,h
if(isGraphicShrinked)then w = w*2 h = h*3 end
for k,v in pairs(graphicObjects)do
for a,b in pairs(v[1])do
setBG(b.x, b.y, w, h, v[2])
end
end
if(isGraphicShrinked)then
shrink()
end
end
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("GraphicBG")
end,
getType = function(self)
return objectType
end;
setSize = function(self, width, height, rel)
base.setSize(self, width, height, rel)
if not(canvasSizeChanged)then
w = width
h = height
redrawCanvasSize()
setOffset = function(self, _x, _y, rel)
if(rel)then
xOffset = xOffset + _x or 0
yOffset = yOffset + _y or 0
else
xOffset = _x or xOffset
yOffset = _y or yOffset
end
redraw()
self:updateDraw()
return self
end,
setOffset = function(self, x, y)
xOffset = x or xOffset
yOffset = y or yOffset
return self
end,
setCanvasSize = function(self, width, height)
w,h = width,height
canvasSizeChanged = true
redrawCanvasSize()
return self
end,
clearCanvas = function(self)
graphicObjects = {}
graphic = {}
redrawCanvasSize()
end,
getOffset = function(self)
return xOffset,yOffset
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("text", data)~=nil)then self:setText(xmlValue("text", data)) end
if(xmlValue("xOffset", data)~=nil)then self:setOffset(xmlValue("xOffset", data), yOffset) end
if(xmlValue("yOffset", data)~=nil)then self:setOffset(xOffset, xmlValue("yOffset", data)) end
if(xmlValue("wCanvas", data)~=nil)then w = xmlValue("wCanvas", data) end
if(xmlValue("hCanvas", data)~=nil)then h = xmlValue("hCanvas", data) end
if(xmlValue("shrink", data)~=nil)then if(xmlValue("shrink", data))then self:shrink() end end
if(xmlValue("dragable", data)~=nil)then if(xmlValue("dragable", data))then dragable = true end end
if(data["ellipse"]~=nil)then
local tab = data["ellipse"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local rad1 = xmlValue("radius", v)
local rad2 = xmlValue("radius2", v)
local x = xmlValue("x", v)
local y = xmlValue("y", v)
local filled = xmlValue("filled", v)
self:addEllipse(col, rad1, rad2, x, y, filled)
end
end
if(data["circle"]~=nil)then
local tab = data["circle"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local rad = tonumber(xmlValue("radius", v))
local x = tonumber(xmlValue("x", v))
local y = tonumber(xmlValue("y", v))
local filled = xmlValue("filled", v)
self:addCircle(col, rad, x, y, filled)
end
end
if(data["line"]~=nil)then
local tab = data["line"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local x = tonumber(xmlValue("x", v))
local x2 = tonumber(xmlValue("x2", v))
local y = tonumber(xmlValue("y", v))
local y2 = tonumber(xmlValue("y2", v))
self:addLine(col, x, y, x2, y2)
end
end
if(data["rectangle"]~=nil)then
local tab = data["rectangle"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local x = tonumber(xmlValue("x", v))
local x2 = tonumber(xmlValue("x2", v))
local y = tonumber(xmlValue("y", v))
local y2 = tonumber(xmlValue("y2", v))
local filled = xmlValue("filled", v)=="true" and true or false
self:addRectangle(col, x, y, x2, y2, filled)
end
end
if(data["triangle"]~=nil)then
local tab = data["triangle"]
if(tab.properties~=nil)then tab = {tab} end
for k,v in pairs(tab)do
local col = colors[xmlValue("color", v)]
local x = tonumber(xmlValue("x", v))
local x2 = tonumber(xmlValue("x2", v))
local x3 = tonumber(xmlValue("x2", v))
local y = tonumber(xmlValue("y", v))
local y2 = tonumber(xmlValue("y2", v))
local y3 = tonumber(xmlValue("y3", v))
local filled = xmlValue("filled", v)
self:addTriangle(col, x, y, x2, y2, x3, y3, filled)
end
end
return self
end,
addCircle = function(self, color, rad, x, y, filled)
local col = tHex[color]
table.insert(graphicObjects, {geometric.circle(x or 1, y or 1, rad, filled), tHex[color]})
redraw()
return self
end;
addEllipse = function(self, color, rad, rad2, x, y, filled)
table.insert(graphicObjects, {geometric.ellipse(x or 1, y or 1, rad, rad2, filled), tHex[color]})
redraw()
return self
end;
addLine = function(self, color, x1, y1, x2, y2)
table.insert(graphicObjects, {geometric.line(x1 or 1, y1 or 1, x2 or 1, y2 or 1), tHex[color]})
redraw()
return self
end;
addTriangle = function(self, color, x1, y1, x2, y2, x3, y3, filled)
table.insert(graphicObjects, {geometric.triangle(x1 or 1, y1 or 1, x2 or 1, y2 or 1, x3 or 1, y3 or 1, filled), tHex[color]})
redraw()
return self
end;
addRectangle = function(self, color, x1, y1, x2, y2, filled)
table.insert(graphicObjects, {geometric.rectangle(x1 or 1, y1 or 1, x2 or 1, y2 or 1, filled), tHex[color]})
redraw()
return self
end;
shrink = function(self)
isGraphicShrinked = true
redrawCanvasSize()
shrink()
return self
end,
setDragable = function(self, drag)
dragable = drag == true and true or false
return self
end,
mouseHandler = function(self, event, button, x, y)
if(base.mouseHandler(self, event, button, x, y))then
if(dragable)then
if(event=="mouse_click")then
xMouse,yMouse = x,y
end
if(event=="mouse_drag")then
if(xMouse~=nil)and(yMouse~=nil)then
xOffset = max(min(xOffset+xMouse-x, w-self:getWidth()),0)
xMouse = x
yOffset = max(min(yOffset+yMouse-y, h-self:getHeight()),0)
yMouse = y
end
end
end
return true
selectFrame = function(self, id)
if(imgData.getFrameObject(id)==nil)then
imgData.addFrame(id)
end
return false
bimgFrame = imgData.getFrameObject(id)
bimg = bimgFrame.getImage(id)
selectedFrame = id
self:updateDraw()
end,
addFrame = function(self, id)
imgData.addFrame(id)
return self
end,
getFrameMetadata = function(self, id, key)
return imgData.getFrameData(id, key)
end,
setFrameMetadata = function(self, id, key, val)
imgData.setFrameData(id, key, val)
return self
end,
getMetadata = function(self, key)
return imgData.getMetadata(key)
end,
setMetadata = function(self, key, value)
return imgData.setMetadata(key, value)
end,
getFrame = function(self, id)
return imgData.getFrame(id)
end,
getFrameObject = function(self, id)
return imgData.getFrameObject(id)
end,
removeFrame = function(self, id)
imgData.removeFrame(id)
return self
end,
moveFrame = function(self, id, dir)
imgData.moveFrame(id, dir)
return self
end,
getFrames = function(self)
return imgData.getFrames()
end,
getFrameCount = function(self)
return #imgData.getFrames()
end,
getSelectedFrame = function(self)
return selectedFrame
end,
blit = function(self, text, fg, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.blit(text, fg, bg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setText = function(self, text, _x, _y)
x = _x or x
y = _y or y
bimgFrame.text(text, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setBg = function(self, bg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.bg(bg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
setFg = function(self, fg, _x, _y)
x = _x or x
y = _y or y
bimgFrame.fg(fg, x, y)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
getImageSize = function(self)
return imgData.getSize()
end,
setImageSize = function(self, w, h)
imgData.setSize(w, h)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
resizeImage = function(self, w, h)
local newBimg = images.resizeBIMG(imgData.createBimg(), w, h)
imgData = bimgLib(newBimg)
selectedFrame = 1
bimgFrame = imgData.getFrameObject(1)
bimg = bimgFrame.getImage()
self:updateDraw()
return self
end,
loadImage = function(self, path)
if(fs.exists(path))then
local newBimg = images.loadBIMG(path)
imgData = bimgLib(newBimg)
selectedFrame = 1
bimgFrame = imgData.getFrameObject(1)
bimg = bimgFrame.getImage()
self:updateDraw()
end
return self
end,
clear = function(self)
imgData = bimgLib()
bimg = nil
self:updateDraw()
return self
end,
getImage = function(self)
return imgData.createBimg()
end,
draw = function(self)
@@ -430,41 +192,22 @@ return function(name)
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if(self.bgColor~=false)then
self.parent:drawBackgroundBox(obx, oby, w, h, self.bgColor)
end
if (isGraphicShrinked) then
-- this is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local t, tC, bC = shrinkedGraphic[1], shrinkedGraphic[2], shrinkedGraphic[3]
for i = 1, shrinkedGraphic.height do
local x, y = obx+xOffset, oby + i - 1 + yOffset
if(y>oby-1)and(y<=oby+h-1)and(x<=w+obx)then
local tI = t[i]
local xpos,substart,subend = max(x, obx), max(1 - x + 1, 1), min(w - (x-obx), w)
if type(tI) == "string" then
self.parent:setText(xpos, y, sub(tI, substart, subend))
self.parent:setFG(xpos, y, sub(tC[i], substart, subend))
self.parent:setBG(xpos, y, sub(bC[i], substart, subend))
elseif type(tI) == "table" then
self.parent:setText(xpos, y, sub(tI[2], substart, subend))
self.parent:setFG(xpos, y, sub(tC[i], substart, subend))
self.parent:setBG(xpos, y, sub(bC[i], substart, subend))
end
end
end
else
for i = 1, #graphic do
local x, y = obx+xOffset, oby + i - 1 + yOffset
if(y>oby-1)and(y<=oby+h-1)and(x<=w+obx)then
local xpos,substart,subend = max(x, obx), max(1 - x + 1, 1), min(w - (x-obx), w)
self.parent:setBG(xpos, y, sub(graphic[i],substart,subend))
if(bimg~=nil)then
for k,v in pairs(bimg)do
if(k<=h-yOffset)and(k+yOffset>=1)then
self.parent:blit(obx+xOffset, oby+k-1+yOffset, v[1], v[2], v[3])
end
end
end
end
self:setVisualChanged(false)
end
end;
end,
init = function(self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("GraphicBG")
end
end,
}
return setmetatable(object, base)

View File

@@ -1,197 +1,158 @@
local Object = require("Object")
local xmlValue = require("utils").getValueFromXML
local images = require("images")
local unpack,sub = table.unpack,string.sub
return function(name)
-- Image
local base = Object(name)
local objectType = "Image"
base:setZIndex(2)
local originalImage
local image
local shrinkedImage
local imageGotShrinked = false
local curFrame = 1
local infinitePlay = false
local animTimer
local usePalette = false
local function shrink()
-- shrinkSystem is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local relations = { [0] = { 8, 4, 3, 6, 5 }, { 4, 14, 8, 7 }, { 6, 10, 8, 7 }, { 9, 11, 8, 0 }, { 1, 14, 8, 0 }, { 13, 12, 8, 0 }, { 2, 10, 8, 0 }, { 15, 8, 10, 11, 12, 14 },
{ 0, 7, 1, 9, 2, 13 }, { 3, 11, 8, 7 }, { 2, 6, 7, 15 }, { 9, 3, 7, 15 }, { 13, 5, 7, 15 }, { 5, 12, 8, 7 }, { 1, 4, 7, 15 }, { 7, 10, 11, 12, 14 } }
base.width = 24
base.height = 8
local colourNum, exponents, colourChar = {}, {}, {}
for i = 0, 15 do
exponents[2 ^ i] = i
end
do
local hex = "0123456789abcdef"
for i = 1, 16 do
colourNum[hex:sub(i, i)] = i - 1
colourNum[i - 1] = hex:sub(i, i)
colourChar[hex:sub(i, i)] = 2 ^ (i - 1)
colourChar[2 ^ (i - 1)] = hex:sub(i, i)
local thisRel = relations[i - 1]
for i = 1, #thisRel do
thisRel[i] = 2 ^ thisRel[i]
local function getPalette(id)
if(originalImage~=nil)then
local p = {}
for k,v in pairs(colors)do
if(type(v)=="number")then
p[v] = {term.nativePaletteColor(v)}
end
end
end
local function getBestColourMatch(usage)
local lastCol = relations[exponents[usage[#usage][1]]]
for j = 1, #lastCol do
local thisRelation = lastCol[j]
for i = 1, #usage - 1 do
if usage[i][1] == thisRelation then
return i
end
if(originalImage.palette~=nil)then
for k,v in pairs(originalImage.palette)do
p[2^k] = v
end
end
return 1
end
local function colsToChar(pattern, totals)
if not totals then
local newPattern = {}
totals = {}
for i = 1, 6 do
local thisVal = pattern[i]
local thisTot = totals[thisVal]
totals[thisVal], newPattern[i] = thisTot and (thisTot + 1) or 1, thisVal
if(originalImage[id]~=nil)and(originalImage[id].palette~=nil)then
for k,v in pairs(originalImage[id].palette)do
p[2^k] = v
end
pattern = newPattern
end
local usage = {}
for key, value in pairs(totals) do
usage[#usage + 1] = { key, value }
end
if #usage > 1 then
-- Reduce the chunk to two colours:
while #usage > 2 do
table.sort(usage, function(a, b)
return a[2] > b[2]
end)
local matchToInd, usageLen = getBestColourMatch(usage), #usage
local matchFrom, matchTo = usage[usageLen][1], usage[matchToInd][1]
for i = 1, 6 do
if pattern[i] == matchFrom then
pattern[i] = matchTo
usage[matchToInd][2] = usage[matchToInd][2] + 1
end
end
usage[usageLen] = nil
end
-- Convert to character. Adapted from oli414's function:
-- http://www.computercraft.info/forums2/index.php?/topic/25340-cc-176-easy-drawing-characters/
local data = 128
for i = 1, #pattern - 1 do
if pattern[i] ~= pattern[6] then
data = data + 2 ^ (i - 1)
end
end
return string.char(data), colourChar[usage[1][1] == pattern[6] and usage[2][1] or usage[1][1]], colourChar[pattern[6]]
else
-- Solid colour character:
return "\128", colourChar[pattern[1]], colourChar[pattern[1]]
end
return p
end
local results, width, height, bgCol = { {}, {}, {} }, 0, #image + #image % 3, base.bgColor or colors.black
for i = 1, #image do
if #image[i] > width then
width = #image[i]
end
end
for y = 0, height - 1, 3 do
local cRow, tRow, bRow, counter = {}, {}, {}, 1
for x = 0, width - 1, 2 do
-- Grab a 2x3 chunk:
local pattern, totals = {}, {}
for yy = 1, 3 do
for xx = 1, 2 do
pattern[#pattern + 1] = (image[y + yy] and image[y + yy][x + xx]) and (image[y + yy][x + xx] == 0 and bgCol or image[y + yy][x + xx]) or bgCol
totals[pattern[#pattern]] = totals[pattern[#pattern]] and (totals[pattern[#pattern]] + 1) or 1
end
end
cRow[counter], tRow[counter], bRow[counter] = colsToChar(pattern, totals)
counter = counter + 1
end
results[1][#results[1] + 1], results[2][#results[2] + 1], results[3][#results[3] + 1] = table.concat(cRow), table.concat(tRow), table.concat(bRow)
end
results.width, results.height = #results[1][1], #results[1]
shrinkedImage = results
end
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ImageBG")
if(base.init(self))then
self.bgColor = self.parent:getTheme("ImageBG")
end
end,
getType = function(self)
return objectType
end;
loadImage = function(self, path)
image = paintutils.loadImage(path)
imageGotShrinked = false
loadImage = function(self, path, f)
if not(fs.exists(path))then error("No valid path: "..path) end
originalImage = images.loadImageAsBimg(path, f)
curFrame = 1
image = originalImage
if(animTimer~=nil)then
os.cancelTimer(animTimer)
end
self:updateDraw()
return self
end;
shrink = function(self)
shrink()
imageGotShrinked = true
setImage = function(self, data)
originalImage = data
image = originalImage
curFrame = 1
if(animTimer~=nil)then
os.cancelTimer(animTimer)
end
self:updateDraw()
return self
end;
end,
usePalette = function(self, use)
usePalette = use~=nil and use or true
return self
end,
play = function(self, inf)
if(originalImage.animated)then
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2
self.parent:addEvent("other_event", self)
animTimer = os.startTimer(t)
infinitePlay = inf or false
end
return self
end,
selectFrame = function(self, fr)
if(originalImage[fr]~=nil)then
curFrame = fr
if(animTimer~=nil)then
os.cancelTimer(animTimer)
end
self:updateDraw()
end
end,
eventHandler = function(self, event, timerId, ...)
base.eventHandler(self, event, timerId, ...)
if(event=="timer")then
if(timerId==animTimer)then
if(originalImage[curFrame+1]~=nil)then
curFrame = curFrame + 1
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2
animTimer = os.startTimer(t)
else
if(infinitePlay)then
curFrame = 1
local t = originalImage[curFrame].duration or originalImage.secondsPerFrame or 0.2
animTimer = os.startTimer(t)
end
end
self:updateDraw()
end
end
end,
getMetadata = function(self, key)
return originalImage[key]
end,
getImageSize = function(self)
return originalImage.width, originalImage.height
end,
resizeImage = function(self, w, h)
image = images.resizeBIMG(originalImage, w, h)
self:updateDraw()
return self
end,
setValuesByXMLData = function(self, data)
base.setValuesByXMLData(self, data)
if(xmlValue("shrink", data)~=nil)then if(xmlValue("shrink", data))then self:shrink() end end
if(xmlValue("path", data)~=nil)then self:loadImage(xmlValue("path", data)) end
return self
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
if (image ~= nil) then
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if (imageGotShrinked) then
-- this is copy pasted (and slightly changed) from blittle by Bomb Bloke: http://www.computercraft.info/forums2/index.php?/topic/25354-cc-176-blittle-api/
local t, tC, bC = shrinkedImage[1], shrinkedImage[2], shrinkedImage[3]
for i = 1, shrinkedImage.height do
local tI = t[i]
if type(tI) == "string" then
self.parent:setText(obx, oby + i - 1, tI)
self.parent:setFG(obx, oby + i - 1, tC[i])
self.parent:setBG(obx, oby + i - 1, bC[i])
elseif type(tI) == "table" then
self.parent:setText(obx, oby + i - 1, tI[2])
self.parent:setFG(obx, oby + i - 1, tC[i])
self.parent:setBG(obx, oby + i - 1, bC[i])
end
end
else
for yPos = 1, math.min(#image, h) do
local line = image[yPos]
for xPos = 1, math.min(#line, w) do
if line[xPos] > 0 then
self.parent:drawBackgroundBox(obx + xPos - 1, oby + yPos - 1, 1, 1, line[xPos])
end
end
end
end
if (image ~= nil) then
if(usePalette)then
self:getBaseFrame():setThemeColor(getPalette(curFrame))
end
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
for y,v in ipairs(image[curFrame])do
local t, f, b = unpack(v)
t = sub(t, 1,w)
f = sub(f, 1,w)
b = sub(b, 1,w)
self.parent:blit(obx, oby+y-1, t, f, b)
if(y==h)then break end
end
end
end

View File

@@ -57,9 +57,9 @@ return function(name)
setValue = function(self, val)
base.setValue(self, tostring(val))
if not (internalValueChange) then
textX = tostring(val):len() + 1
wIndex = math.max(1, textX-self:getWidth()+1)
if(self:isFocused())then
textX = tostring(val):len() + 1
wIndex = math.max(1, textX-self:getWidth()+1)
local obx, oby = self:getAnchorPosition()
self.parent:setCursor(true, obx + textX - wIndex, oby+math.floor(self:getHeight()/2), self.fgColor)
end
@@ -202,12 +202,15 @@ return function(name)
if (text:len() < inputLimit or inputLimit <= 0) then
if (inputType == "number") then
local cache = text
if (char == ".") or (tonumber(char) ~= nil) then
if (textX==1 and char == "-") or (char == ".") or (tonumber(char) ~= nil) then
self:setValue(text:sub(1, textX - 1) .. char .. text:sub(textX, text:len()))
textX = textX + 1
end
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
if(char==".")or(char=="-")and(#text>0)then
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
textX = textX - 1
end
end
end
else
self:setValue(text:sub(1, textX - 1) .. char .. text:sub(textX, text:len()))
@@ -267,44 +270,43 @@ return function(name)
end
end,
eventHandler = function(self, event, paste, p2, p3, p4)
if(base.eventHandler(self, event, paste, p2, p3, p4))then
if(event=="paste")then
if(self:isFocused())then
local text = base.getValue()
local w, h = self:getSize()
internalValueChange = true
if (inputType == "number") then
local cache = text
if (paste == ".") or (tonumber(paste) ~= nil) then
self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len()))
textX = textX + paste:len()
end
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
end
else
eventHandler = function(self, event, paste, ...)
base.eventHandler(self, event, paste, ...)
if(event=="paste")then
if(self:isFocused())then
local text = base.getValue()
local w, h = self:getSize()
internalValueChange = true
if (inputType == "number") then
local cache = text
if (paste == ".") or (tonumber(paste) ~= nil) then
self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len()))
textX = textX + paste:len()
end
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
if (tonumber(base.getValue()) == nil) then
self:setValue(cache)
end
local obx, oby = self:getAnchorPosition()
local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
local x = self:getX()
if (cursorX > x + w - 1) then
cursorX = x + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end
self:updateDraw()
internalValueChange = false
else
self:setValue(text:sub(1, textX - 1) .. paste .. text:sub(textX, text:len()))
textX = textX + paste:len()
end
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
end
local obx, oby = self:getAnchorPosition()
local val = tostring(base.getValue())
local cursorX = (textX <= val:len() and textX - 1 or val:len()) - (wIndex - 1)
local x = self:getX()
if (cursorX > x + w - 1) then
cursorX = x + w - 1
end
if (self.parent ~= nil) then
self.parent:setCursor(true, obx + cursorX, oby+math.max(math.ceil(h/2-1, 1)), self.fgColor)
end
self:updateDraw()
internalValueChange = false
end
end
end,
@@ -353,8 +355,6 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("InputBG")
self.fgColor = self.parent:getTheme("InputText")
if(self.parent~=nil)then
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("key", self)
@@ -362,6 +362,10 @@ return function(name)
self.parent:addEvent("other_event", self)
self.parent:addEvent("mouse_drag", self)
end
if(base.init(self))then
self.bgColor = self.parent:getTheme("InputBG")
self.fgColor = self.parent:getTheme("InputText")
end
end,
}

View File

@@ -31,7 +31,13 @@ return function(name)
text = tostring(text)
base:setValue(text)
if (autoSize) then
self.width = text:len()
local xOffset = self.parent:getOffset()
if(text:len()+self:getX()>self.parent:getWidth()+xOffset)then
local newW = self.parent:getWidth()+xOffset - self:getX()
base.setSize(self, newW, #createText(text, newW))
else
base.setSize(self, text:len(), 1)
end
end
self:updateDraw()
return self
@@ -86,6 +92,22 @@ return function(name)
return self
end;
eventHandler = function(self, event)
if(event=="basalt_resize")then
if (autoSize) then
local text = self:getValue()
if(text:len()+self:getX()>self.parent:getWidth())then
local newW = self.parent:getWidth() - self:getX()
base.setSize(self, newW, #createText(text, newW))
else
base.setSize(self, text:len(), 1)
end
else
--self.parent:removeEvent("other_event", self)
end
end
end,
draw = function(self)
if (base.draw(self)) then
if (self.parent ~= nil) then
@@ -96,10 +118,21 @@ return function(name)
if not(autoSize)then
local text = createText(self:getValue(), self:getWidth())
for k,v in pairs(text)do
self.parent:writeText(obx, oby+k-1, v, self.bgColor, self.fgColor)
if(k<=h)then
self.parent:writeText(obx, oby+k-1, v, self.bgColor, self.fgColor)
end
end
else
self.parent:writeText(obx, oby, self:getValue(), self.bgColor, self.fgColor)
if(#self:getValue()+obx>self.parent:getWidth())then
local text = createText(self:getValue(), self:getWidth())
for k,v in pairs(text)do
if(k<=h)then
self.parent:writeText(obx, oby+k-1, v, self.bgColor, self.fgColor)
end
end
else
self.parent:writeText(obx, oby, self:getValue(), self.bgColor, self.fgColor)
end
end
else
local tData = bigFont(fontsize, self:getValue(), self.fgColor, self.bgColor or colors.lightGray)
@@ -112,15 +145,16 @@ return function(name)
oby = oby or math.floor((oY - cY) / 2) + 1
for i = 1, cY do
self.parent:setFG(obx, oby + i - 2, tData[2][i])
self.parent:setBG(obx, oby + i - 2, tData[3][i])
self.parent:setText(obx, oby + i - 2, tData[1][i])
self.parent:setFG(obx, oby + i - 1, tData[2][i])
self.parent:setBG(obx, oby + i - 1, tData[3][i])
self.parent:setText(obx, oby + i - 1, tData[1][i])
end
end
end
end
end,
init = function(self)
self.parent:addEvent("other_event", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("LabelBG")
self.fgColor = self.parent:getTheme("LabelText")

View File

@@ -24,8 +24,8 @@ return function(name)
addItem = function(self, text, bgCol, fgCol, ...)
table.insert(list, { text = text, bgCol = bgCol or self.bgColor, fgCol = fgCol or self.fgColor, args = { ... } })
if (#list == 1) then
self:setValue(list[1])
if (#list <= 1) then
self:setValue(list[1], false)
end
self:updateDraw()
return self
@@ -66,7 +66,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -83,7 +83,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
@@ -199,13 +199,15 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("ListBG")
self.fgColor = self.parent:getTheme("ListText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ListBG")
self.fgColor = self.parent:getTheme("ListText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end
end,
}

View File

@@ -68,7 +68,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -142,7 +142,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
@@ -226,14 +226,14 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarText")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
end
end,
}

View File

@@ -2,7 +2,6 @@ local Object = require("Object")
local tHex = require("tHex")
local process = require("process")
local xmlValue = require("utils").getValueFromXML
local log = require("basaltLogs")
local sub = string.sub
@@ -12,6 +11,7 @@ return function(name, parent)
base:setZIndex(5)
local object
local cachedPath
local enviroment = {}
local function createBasaltWindow(x, y, width, height, self)
local xCursor, yCursor = 1, 1
@@ -428,7 +428,21 @@ return function(name, parent)
local obx, oby = self:getAnchorPosition()
local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
self.parent:setCursor(self:isFocused() and pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
local function resumeProcess(self, event, ...)
local ok, result = curProcess:resume(event, ...)
if (ok==false)and(result~=nil)and(result~="Terminated")then
local val = self:sendEvent("program_error", result)
if(val~=false)then
error("Basalt Program - "..result)
end
end
if(curProcess:getStatus()=="dead")then
self:sendEvent("program_done")
end
end
@@ -439,7 +453,7 @@ return function(name, parent)
if not (curProcess:isDead()) then
if not (paused) then
local absX, absY = self:getAbsolutePosition(self:getAnchorPosition(nil, nil, true))
curProcess:resume(event, p1, x-absX+1, y-absY+1)
resumeProcess(self, event, p1, x-absX+1, y-absY+1)
updateCursor(self)
end
end
@@ -452,7 +466,7 @@ return function(name, parent)
if not (curProcess:isDead()) then
if not (paused) then
if (self.draw) then
curProcess:resume(event, key, isHolding)
resumeProcess(self, event, key, isHolding)
updateCursor(self)
end
end
@@ -511,9 +525,14 @@ return function(name, parent)
return "inactive"
end;
setEnviroment = function(self, env)
enviroment = env or {}
return self
end,
execute = function(self, path, ...)
cachedPath = path or cachedPath
curProcess = process:new(cachedPath, pWindow, ...)
curProcess = process:new(cachedPath, pWindow, enviroment, ...)
pWindow.setBackgroundColor(colors.black)
pWindow.setTextColor(colors.white)
pWindow.clear()
@@ -521,7 +540,8 @@ return function(name, parent)
pWindow.setBackgroundColor(self.bgColor)
pWindow.setTextColor(self.fgColor)
pWindow.basalt_setVisible(true)
curProcess:resume()
resumeProcess(self)
paused = false
if(self.parent~=nil)then
self.parent:addEvent("mouse_click", self)
@@ -539,7 +559,7 @@ return function(name, parent)
stop = function(self)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
curProcess:resume("terminate")
resumeProcess(self, "terminate")
if (curProcess:isDead()) then
if (self.parent ~= nil) then
self.parent:setCursor(false)
@@ -572,7 +592,7 @@ return function(name, parent)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
if (paused == false) or (ign) then
curProcess:resume(event, p1, p2, p3, p4)
resumeProcess(self, event, p1, p2, p3, p4)
else
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } })
end
@@ -594,7 +614,7 @@ return function(name, parent)
if (curProcess ~= nil) then
if not (curProcess:isDead()) then
for _, value in pairs(events) do
curProcess:resume(value.event, table.unpack(value.args))
resumeProcess(self, value.event, table.unpack(value.args))
end
end
end
@@ -665,11 +685,9 @@ return function(name, parent)
if (self.parent ~= nil) then
local xCur, yCur = pWindow.getCursorPos()
local obx, oby = self:getAnchorPosition()
if (self.parent ~= nil) then
local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
end
@@ -687,51 +705,55 @@ return function(name, parent)
end
end
end,
customEventHandler = function(self, event, ...)
base.customEventHandler(self, event, ...)
if (curProcess == nil) then
return
end
if(event=="basalt_resize")then
local w, h = pWindow.getSize()
local pW, pH = self:getSize()
if(w~=pW)or(h~=pH)then
pWindow.basalt_resize(pW, pH)
if not (curProcess:isDead()) then
resumeProcess(self, "term_resize")
end
end
pWindow.basalt_reposition(self:getAnchorPosition())
end
end,
eventHandler = function(self, event, p1, p2, p3, p4)
if(base.eventHandler(self, event, p1, p2, p3, p4))then
if (curProcess == nil) then
return
end
if(event=="dynamicValueEvent")then
local w, h = pWindow.getSize()
local pW, pH = self:getSize()
if(w~=pW)or(h~=pH)then
pWindow.basalt_resize(pW, pH)
if not (curProcess:isDead()) then
curProcess:resume("term_resize")
end
base.eventHandler(self, event, p1, p2, p3, p4)
if (curProcess == nil) then
return
end
if not (curProcess:isDead()) then
if not (paused) then
if(event ~= "terminate") then
resumeProcess(self, event, p1, p2, p3, p4)
end
pWindow.basalt_reposition(self:getAnchorPosition())
end
if not (curProcess:isDead()) then
if not (paused) then
if(event ~= "terminate") then
curProcess:resume(event, p1, p2, p3, p4)
end
if (self:isFocused()) then
local obx, oby = self:getAnchorPosition()
local xCur, yCur = pWindow.getCursorPos()
if (self.parent ~= nil) then
local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
if (self:isFocused()) then
local obx, oby = self:getAnchorPosition()
local xCur, yCur = pWindow.getCursorPos()
if (self.parent ~= nil) then
local w,h = self:getSize()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
if (event == "terminate") then
log(self:isFocused())
curProcess:resume(event)
self.parent:setCursor(false)
return true
end
if (event == "terminate") then
resumeProcess(self, event)
self.parent:setCursor(false)
return true
end
else
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } })
end
else
table.insert(queuedEvent, { event = event, args = { p1, p2, p3, p4 } })
end
return false
end
end,
@@ -739,18 +761,48 @@ return function(name, parent)
if (base.draw(self)) then
if (self.parent ~= nil) then
local obx, oby = self:getAnchorPosition()
local xCur, yCur = pWindow.getCursorPos()
local w,h = self:getSize()
pWindow.basalt_reposition(obx, oby)
pWindow.basalt_update()
if (obx + xCur - 1 >= 1 and obx + xCur - 1 <= obx + w - 1 and yCur + oby - 1 >= 1 and yCur + oby - 1 <= oby + h - 1) then
self.parent:setCursor(self:isFocused() and pWindow.getCursorBlink(), obx + xCur - 1, yCur + oby - 1, pWindow.getTextColor())
end
end
end
end,
onError = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("program_error", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("other_event", self)
end
return self
end,
onDone = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("program_done", v)
end
end
if(self.parent~=nil)then
self.parent:addEvent("other_event", self)
end
return self
end,
init = function(self)
self.bgColor = self.parent:getTheme("ProgramBG")
if(base.init(self))then
self.bgColor = self.parent:getTheme("ProgramBG")
end
end,
}
return setmetatable(object, base)
end
end

View File

@@ -21,9 +21,11 @@ return function(name)
local object = {
init = function(self)
self.bgColor = self.parent:getTheme("ProgressbarBG")
self.fgColor = self.parent:getTheme("ProgressbarText")
activeBarColor = self.parent:getTheme("ProgressbarActiveBG")
if(base.init(self))then
self.bgColor = self.parent:getTheme("ProgressbarBG")
self.fgColor = self.parent:getTheme("ProgressbarText")
activeBarColor = self.parent:getTheme("ProgressbarActiveBG")
end
end,
getType = function(self)
return objectType

View File

@@ -77,7 +77,7 @@ return function(name)
clear = function(self)
list = {}
self:setValue({})
self:setValue({}, false)
self:updateDraw()
return self
end;
@@ -94,7 +94,7 @@ return function(name)
end;
selectItem = function(self, index)
self:setValue(list[index] or {})
self:setValue(list[index] or {}, false)
self:updateDraw()
return self
end;
@@ -153,13 +153,15 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarFG")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
boxSelectedBG = self.parent:getTheme("MenubarBG")
boxSelectedFG = self.parent:getTheme("MenubarText")
self.parent:addEvent("mouse_click", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("MenubarBG")
self.fgColor = self.parent:getTheme("MenubarFG")
itemSelectedBG = self.parent:getTheme("SelectionBG")
itemSelectedFG = self.parent:getTheme("SelectionText")
boxSelectedBG = self.parent:getTheme("MenubarBG")
boxSelectedFG = self.parent:getTheme("MenubarText")
end
end,
}

View File

@@ -173,12 +173,14 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("ScrollbarBG")
self.fgColor = self.parent:getTheme("ScrollbarText")
symbolColor = self.parent:getTheme("ScrollbarSymbolColor")
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("ScrollbarBG")
self.fgColor = self.parent:getTheme("ScrollbarText")
symbolColor = self.parent:getTheme("ScrollbarSymbolColor")
end
end,
}

View File

@@ -173,12 +173,14 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("SliderBG")
self.fgColor = self.parent:getTheme("SliderText")
symbolColor = self.parent:getTheme("SliderSymbolColor")
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("mouse_scroll", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("SliderBG")
self.fgColor = self.parent:getTheme("SliderText")
symbolColor = self.parent:getTheme("SliderSymbolColor")
end
end,
}

View File

@@ -74,12 +74,14 @@ return function(name)
end,
init = function(self)
self.bgColor = self.parent:getTheme("SwitchBG")
self.fgColor = self.parent:getTheme("SwitchText")
bgSymbol = self.parent:getTheme("SwitchBGSymbol")
inactiveBG = self.parent:getTheme("SwitchInactive")
activeBG = self.parent:getTheme("SwitchActive")
self.parent:addEvent("mouse_click", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("SwitchBG")
self.fgColor = self.parent:getTheme("SwitchText")
bgSymbol = self.parent:getTheme("SwitchBGSymbol")
inactiveBG = self.parent:getTheme("SwitchInactive")
activeBG = self.parent:getTheme("SwitchActive")
end
end,
}

View File

@@ -1,9 +1,9 @@
local Object = require("Object")
local tHex = require("tHex")
local log = require("basaltLogs")
local xmlValue = require("utils").getValueFromXML
local log = require("basaltLogs")
local rep = string.rep
local rep,find,gmatch,sub,len = string.rep,string.find,string.gmatch,string.sub,string.len
return function(name)
local base = Object(name)
@@ -16,20 +16,86 @@ return function(name)
local keyWords = { }
local rules = { }
local startSelX,endSelX,startSelY,endSelY
local selectionBG,selectionFG = colors.lightBlue,colors.black
base.width = 30
base.height = 12
base:setZIndex(5)
local function isSelected()
if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then
return true
end
return false
end
local function getSelectionCoordinates()
local sx,ex,sy,ey
if(isSelected())then
if(startSelX>endSelX)then
sx,ex = endSelX,startSelX
else
sx,ex = startSelX,endSelX
end
if(startSelY>endSelY)then
sy,ey = endSelY,startSelY
else
sy,ey = startSelY,endSelY
end
end
return sx,ex,sy,ey
end
local function getSelection()
end
local function removeSelection(self)
local sx,ex,sy,ey = getSelectionCoordinates(self)
for n=ey,sy,-1 do
if(n==sy)or(n==ey)then
local l = lines[n]
local b = bgLines[n]
local f = fgLines[n]
if(n==sy)and(n==ey)then
l = l:sub(1,sx-1)..l:sub(ex+1,l:len())
b = b:sub(1,sx-1)..b:sub(ex+1,b:len())
f = f:sub(1,sx-1)..f:sub(ex+1,f:len())
elseif(n==sx)then
l = l:sub(1, sx)
b = b:sub(1, sx)
f = f:sub(1, sx)
elseif(n==sy)then
l = l:sub(ex, l:len())
b = b:sub(ex, b:len())
f = f:sub(ex, f:len())
end
lines[n] = l
bgLines[n] = b
fgLines[n] = f
else
table.remove(lines, n)
table.remove(bgLines, n)
table.remove(fgLines, n)
end
end
textX,textY = startSelX,startSelY
startSelX,endSelX,startSelY,endSelY = nil,nil,nil,nil
return self
end
local function stringGetPositions(str, word)
local pos = {}
if(str:len()>0)then
for w in string.gmatch(str, word)do
local s, e = string.find(str, w)
for w in gmatch(str, word)do
local s, e = find(str, w)
if(s~=nil)and(e~=nil)then
table.insert(pos,s)
table.insert(pos,e)
local startL = string.sub(str, 1, (s-1))
local endL = string.sub(str, e+1, str:len())
local startL = sub(str, 1, (s-1))
local endL = sub(str, e+1, str:len())
str = startL..(":"):rep(w:len())..endL
end
end
@@ -144,6 +210,7 @@ return function(name)
editLine = function(self, index, text)
lines[index] = text or lines[index]
updateColors(self, index)
self:updateDraw()
return self
end;
@@ -152,6 +219,7 @@ return function(name)
lines = {""}
bgLines = {""}
fgLines = {""}
startSelX,endSelX,startSelY,endSelY = nil,nil,nil,nil
hIndex, wIndex, textX, textY = 1, 1, 1, 1
self:updateDraw()
return self
@@ -163,18 +231,20 @@ return function(name)
lines[1] = text
bgLines[1] = tHex[self.bgColor]:rep(text:len())
fgLines[1] = tHex[self.fgColor]:rep(text:len())
updateColors(self, 1)
return self
end
if (index ~= nil) then
table.insert(lines, index, text)
table.insert(bgLines, index, tHex[self.bgColor]:rep(text:len()))
table.insert(fgLines, tHex[self.fgColor]:rep(text:len()))
table.insert(fgLines, index, tHex[self.fgColor]:rep(text:len()))
else
table.insert(lines, text)
table.insert(bgLines, tHex[self.bgColor]:rep(text:len()))
table.insert(fgLines, tHex[self.fgColor]:rep(text:len()))
end
end
updateColors(self, index or #lines)
self:updateDraw()
return self
end;
@@ -224,9 +294,14 @@ return function(name)
end;
removeLine = function(self, index)
table.remove(lines, index or #lines)
if (#lines <= 0) then
table.insert(lines, "")
if(#lines>1)then
table.remove(lines, index or #lines)
table.remove(bgLines, index or #bgLines)
table.remove(fgLines, index or #fgLines)
else
lines = {""}
bgLines = {""}
fgLines = {""}
end
self:updateDraw()
return self
@@ -308,17 +383,21 @@ return function(name)
if (key == keys.delete) then
-- on delete
if (textX > lines[textY]:len()) then
if (lines[textY + 1] ~= nil) then
lines[textY] = lines[textY] .. lines[textY + 1]
table.remove(lines, textY + 1)
table.remove(bgLines, textY + 1)
table.remove(fgLines, textY + 1)
end
if(isSelected())then
removeSelection(self)
else
lines[textY] = lines[textY]:sub(1, textX - 1) .. lines[textY]:sub(textX + 1, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. fgLines[textY]:sub(textX + 1, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. bgLines[textY]:sub(textX + 1, bgLines[textY]:len())
if (textX > lines[textY]:len()) then
if (lines[textY + 1] ~= nil) then
lines[textY] = lines[textY] .. lines[textY + 1]
table.remove(lines, textY + 1)
table.remove(bgLines, textY + 1)
table.remove(fgLines, textY + 1)
end
else
lines[textY] = lines[textY]:sub(1, textX - 1) .. lines[textY]:sub(textX + 1, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. fgLines[textY]:sub(textX + 1, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. bgLines[textY]:sub(textX + 1, bgLines[textY]:len())
end
end
updateColors(self)
end
@@ -427,9 +506,14 @@ return function(name)
end
end
if not((obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h)) then
wIndex = math.max(1, lines[textY]:len()-w+1)
hIndex = math.max(1, textY - h + 1)
end
local cursorX = (textX <= lines[textY]:len() and textX - 1 or lines[textY]:len()) - (wIndex - 1)
if (cursorX > self.x + w - 1) then
cursorX = self.x + w - 1
if (cursorX > self:getX() + w - 1) then
cursorX = self:getX() + w - 1
end
local cursorY = (textY - hIndex < h and textY - hIndex or textY - hIndex - 1)
if (cursorX < 1) then
@@ -455,14 +539,22 @@ return function(name)
updateColors(self)
self:setValue("")
if not((obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h)) then
wIndex = math.max(1, lines[textY]:len()-w+1)
hIndex = math.max(1, textY - h + 1)
end
local cursorX = (textX <= lines[textY]:len() and textX - 1 or lines[textY]:len()) - (wIndex - 1)
if (cursorX > self.x + w - 1) then
cursorX = self.x + w - 1
if (cursorX > self:getX() + w - 1) then
cursorX = self:getX() + w - 1
end
local cursorY = (textY - hIndex < h and textY - hIndex or textY - hIndex - 1)
if (cursorX < 1) then
cursorX = 0
end
if(isSelected())then
removeSelection(self)
end
self.parent:setCursor(true, obx + cursorX, oby + cursorY, self.fgColor)
self:updateDraw()
return true
@@ -478,18 +570,21 @@ return function(name)
if(anchx+w > anchx + x - (obx+1)+ wIndex)and(anchx < anchx + x - obx+ wIndex)then
textX = x - obx + wIndex
textY = y - oby + hIndex
endSelX = textX
endSelY = textY
if (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1
endSelX = textX
end
if (textX < wIndex) then
wIndex = textX - 1
if (wIndex < 1) then
wIndex = 1
end
end
if (self.parent ~= nil) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
self:updateDraw()
end
end
@@ -511,12 +606,10 @@ return function(name)
hIndex = 1
end
if (self.parent ~= nil) then
if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (oby + textY - hIndex >= oby and oby + textY - hIndex < oby + h) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
else
self.parent:setCursor(false)
end
if (obx + textX - wIndex >= obx and obx + textX - wIndex < obx + w) and (anchy + textY - hIndex >= anchy and anchy + textY - hIndex < anchy + h) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
else
self.parent:setCursor(false)
end
self:updateDraw()
return true
@@ -530,8 +623,13 @@ return function(name)
if (lines[y - oby + hIndex] ~= nil) then
textX = x - obx + wIndex
textY = y - oby + hIndex
endSelX = nil
endSelY = nil
startSelX = textX
startSelY = textY
if (textX > lines[textY]:len()) then
textX = lines[textY]:len() + 1
startSelX = textX
end
if (textX < wIndex) then
wIndex = textX - 1
@@ -539,6 +637,7 @@ return function(name)
wIndex = 1
end
end
self:updateDraw()
end
if (self.parent ~= nil) then
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
@@ -547,26 +646,50 @@ return function(name)
end
end,
eventHandler = function(self, event, paste, p2, p3, p4)
if(base.eventHandler(self, event, paste, p2, p3, p4))then
if(event=="paste")then
if(self:isFocused())then
local w, h = self:getSize()
lines[textY] = lines[textY]:sub(1, textX - 1) .. paste .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[self.fgColor]:rep(paste:len()) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self.bgColor]:rep(paste:len()) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
textX = textX + paste:len()
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
mouseUpHandler = function(self, button, x, y)
if (base.mouseUpHandler(self, button, x, y)) then
local obx, oby = self:getAbsolutePosition(self:getAnchorPosition())
local anchx, anchy = self:getAnchorPosition()
if (lines[y - oby + hIndex] ~= nil) then
endSelX = x - obx + wIndex
endSelY = y - oby + hIndex
if (endSelX > lines[endSelY]:len()) then
endSelX = lines[endSelY]:len() + 1
end
local anchx, anchy = self:getAnchorPosition()
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
updateColors(self)
if(startSelX==endSelX)and(startSelY==endSelY)then
startSelX, endSelX, startSelY, endSelY = nil, nil, nil, nil
end
self:updateDraw()
end
return true
end
end,
eventHandler = function(self, event, paste, p2, p3, p4)
base.eventHandler(self, event, paste, p2, p3, p4)
if(event=="paste")then
if(self:isFocused())then
local w, h = self:getSize()
lines[textY] = lines[textY]:sub(1, textX - 1) .. paste .. lines[textY]:sub(textX, lines[textY]:len())
fgLines[textY] = fgLines[textY]:sub(1, textX - 1) .. tHex[self.fgColor]:rep(paste:len()) .. fgLines[textY]:sub(textX, fgLines[textY]:len())
bgLines[textY] = bgLines[textY]:sub(1, textX - 1) .. tHex[self.bgColor]:rep(paste:len()) .. bgLines[textY]:sub(textX, bgLines[textY]:len())
textX = textX + paste:len()
if (textX >= w + wIndex) then
wIndex = (textX+1)-w
end
local anchx, anchy = self:getAnchorPosition()
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
updateColors(self)
self:updateDraw()
end
end
end,
setSelectionColor = function(self, bg, fg)
selectionBG = bg or selectionBG
selectionFG = fg or selectionFG
return self
end,
draw = function(self)
if (base.draw(self)) then
@@ -596,25 +719,47 @@ return function(name)
self.parent:setBG(obx, oby + n - 1, bg)
self.parent:setFG(obx, oby + n - 1, fg)
end
--[[
if(startSelX~=nil)and(endSelX~=nil)and(startSelY~=nil)and(endSelY~=nil)then
local sx,ex,sy,ey = getSelectionCoordinates(self)
for n=sy,ey do
local line = lines[n]:len()
local xOffset = 0
if(n==sy)and(n==ey)then
xOffset = sx-1
line = line - (sx-1) - (line - ex)
elseif(n==ey)then
line = line - (line - ex)
elseif(n==sy)then
line = line-(sx-1)
xOffset = sx-1
end
self.parent:setBG(obx + xOffset, oby + n - 1, rep(tHex[selectionBG], line))
self.parent:setFG(obx + xOffset, oby + n - 1, rep(tHex[selectionFG], line))
end
end]]
if(self:isFocused())then
local anchx, anchy = self:getAnchorPosition()
self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
--self.parent:setCursor(true, anchx + textX - wIndex, anchy + textY - hIndex, self.fgColor)
end
end
end
end,
init = function(self)
self.bgColor = self.parent:getTheme("TextfieldBG")
self.fgColor = self.parent:getTheme("TextfieldText")
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("key", self)
self.parent:addEvent("char", self)
self.parent:addEvent("other_event", self)
if(base.init(self))then
self.bgColor = self.parent:getTheme("TextfieldBG")
self.fgColor = self.parent:getTheme("TextfieldText")
end
end,
}
return setmetatable(object, base)
end
end

View File

@@ -7,6 +7,7 @@ return function(name)
local func
local cRoutine
local isActive = false
local filter
local generateXMLEventFunction = function(self, str)
if(str:sub(1,1)=="#")then
@@ -53,12 +54,21 @@ return function(name)
func = f
cRoutine = coroutine.create(func)
isActive = true
filter=nil
local ok, result = coroutine.resume(cRoutine)
filter = result
if not (ok) then
if (result ~= "Terminated") then
error("Thread Error Occurred - " .. result)
end
end
self.parent:addEvent("mouse_click", self)
self.parent:addEvent("mouse_up", self)
self.parent:addEvent("mouse_scroll", self)
self.parent:addEvent("mouse_drag", self)
self.parent:addEvent("key", self)
self.parent:addEvent("key_up", self)
self.parent:addEvent("char", self)
self.parent:addEvent("other_event", self)
return self
end;
@@ -72,21 +82,58 @@ return function(name)
stop = function(self, f)
isActive = false
self.parent:removeEvent("mouse_click", self)
self.parent:removeEvent("mouse_up", self)
self.parent:removeEvent("mouse_scroll", self)
self.parent:removeEvent("mouse_drag", self)
self.parent:removeEvent("key", self)
self.parent:removeEvent("key_up", self)
self.parent:removeEvent("char", self)
self.parent:removeEvent("other_event", self)
return self
end;
eventHandler = function(self, event, p1, p2, p3)
mouseHandler = function(self, ...)
self:eventHandler("mouse_click", ...)
end,
mouseUpHandler = function(self, ...)
self:eventHandler("mouse_up", ...)
end,
mouseScrollHandler = function(self, ...)
self:eventHandler("mouse_scroll", ...)
end,
mouseDragHandler = function(self, ...)
self:eventHandler("mouse_drag", ...)
end,
mouseMoveHandler = function(self, ...)
self:eventHandler("mouse_move", ...)
end,
keyHandler = function(self, ...)
self:eventHandler("key", ...)
end,
keyUpHandler = function(self, ...)
self:eventHandler("key_up", ...)
end,
charHandler = function(self, ...)
self:eventHandler("char", ...)
end,
eventHandler = function(self, event, ...)
if (isActive) then
if (coroutine.status(cRoutine) ~= "dead") then
local ok, result = coroutine.resume(cRoutine, event, p1, p2, p3)
if (coroutine.status(cRoutine) == "suspended") then
if(filter~=nil)then
if(event~=filter)then return end
filter=nil
end
local ok, result = coroutine.resume(cRoutine, event, ...)
filter = result
if not (ok) then
if (result ~= "Terminated") then
error("Thread Error Occurred - " .. result)
end
end
else
isActive = false
self:stop()
end
end
end;

View File

@@ -40,6 +40,8 @@ return { -- The default main theme for basalt!
SwitchInactive = colors.red,
SwitchActive = colors.green,
LabelBG = false,
LabelText = colors.black
LabelText = colors.black,
GraphBG = colors.gray,
GraphText = colors.black
}

View File

@@ -1,24 +1,19 @@
# Welcome to The Basalt Wiki!
# Welcome to The Basalt Wiki
*Note: The Basalt Wiki is a work in progress. Please treat Wiki errors the same as bugs and report them accordingly.*
*Note: The Basalt Wiki is a work in progress. Please treat wiki errors the same as bugs and report them accordingly.*
Here you can find information about how to use Basalt as well as examples of functional Basalt code. The aim of Basalt is to improve user interaction through visual display.
## About Basalt
Basalt is intended to be an easy-to-understand UI Framework designed for CC:Tweaked (Also know as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://www.curseforge.com/minecraft/mc-mods/cc-tweaked).
Basalt is intended to be an easy-to-understand UI Framework designed for CC:Tweaked (Also known as "ComputerCraft: Tweaked") - a popular minecraft mod. For more information about CC:Tweaked, checkout the project's [wiki](https://tweaked.cc/) or [download](https://modrinth.com/mod/cc-tweaked).
## Quick Demo
<img src="https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/basaltPreview2.gif" width="600">
![Basalt Demo GIF](https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/basaltPreview2.gif)
## Questions & Bugs
Obviously NyoriE has implemented some easter eggs, *some people* call them "bugs". If you happen to discover one of these just make a new <a href="https://github.com/Pyroxenium/Basalt/issues">issue</a>.
Obviously NyoriE has implemented some easter eggs, *some people* call them "bugs". If you happen to discover one of these just make a new [Github Issue](https://github.com/Pyroxenium/Basalt/issues)
Additionally, if you have questions about Basalt or how to make use of it, feel free to create a new discussion on <a href="https://github.com/Pyroxenium/Basalt/discussions">Basalt's Discussion Board</a>, or ask in our [discord](https://discord.gg/yNNnmBVBpE).
---
Feel free to join our [discord](https://discord.gg/yNNnmBVBpE)!
<br><br>
Additionally, if you have questions about Basalt or how to make use of it, feel free to create a new discussion on [Basalt's Discussion Board (Github)](https://github.com/Pyroxenium/Basalt/discussions), or ask in our [discord](https://discord.gg/yNNnmBVBpE).

View File

@@ -1 +1,3 @@
Thanks for checking out our wiki, join our discord for more help: [discord.gg/yM7kndJdJJ](discord.gg/yM7kndJdJJ)
---
Thanks for checking out our wiki, join our discord for more help: [discord.gg/yM7kndJdJJ](discord.gg/yNNnmBVBpE)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
- Getting Started
- [Home](Home.md)
- [Quick Start](home/Quick-Start.md)
- [Installer](home/installer)
- [Home](Home)
- [How To](home/How-To)
- [Download](home/download)

View File

@@ -1,32 +1,32 @@
- About
- [Home](Home.md)
- [Quick Start](home/Quick-Start.md)
- [Installer](home/installer)
- [Home](home)
- [How To](home/How-To)
- [Download](home/download)
- Objects
- [Basalt](objects/Basalt.md)
- [Object](objects/Object.md)
- [Button](objects/Button.md)
- [Checkbox](objects/Checkbox.md)
- [Dropdown](objects/Dropdown.md)
- [Frame](objects/Frame.md)
- [Image](objects/Image.md)
- [Input](objects/Input.md)
- [Label](objects/Label.md)
- [List](objects/List.md)
- [Menubar](objects/Menubar.md)
- [Pane](objects/Pane.md)
- [Program](objects/Program.md)
- [Progressbar](objects/Progressbar.md)
- [Radio](objects/Radio.md)
- [Scrollbar](objects/Scrollbar.md)
- [Slider](objects/Slider.md)
- [Textfield](objects/Textfield.md)
- [Animation](objects/Animation.md)
- [Thread](objects/Thread.md)
- [Timer](objects/Timer.md)
- [Basalt](objects/Basalt.md)
- [Object](objects/Object.md)
- [Button](objects/Button.md)
- [Checkbox](objects/Checkbox.md)
- [Dropdown](objects/Dropdown.md)
- [Frame](objects/Frame.md)
- [Image](objects/Image.md)
- [Input](objects/Input.md)
- [Label](objects/Label.md)
- [List](objects/List.md)
- [Menubar](objects/Menubar.md)
- [Pane](objects/Pane.md)
- [Program](objects/Program.md)
- [Progressbar](objects/Progressbar.md)
- [Radio](objects/Radio.md)
- [Scrollbar](objects/Scrollbar.md)
- [Slider](objects/Slider.md)
- [Textfield](objects/Textfield.md)
- [Animation](objects/Animation.md)
- [Thread](objects/Thread.md)
- [Timer](objects/Timer.md)
- Tips & Tricks
- [Your Logic](tips/logic.md)
- [Button coloring](tips/buttonColoring.md)
- [Designing/Animating](tips/design.md)
- [Dynamic Values](tips/dynamicvalues.md)
- [XML](tips/xml.md)
- [Your Logic](tips/logic.md)
- [Button coloring](tips/buttonColoring.md)
- [Designing/Animating](tips/design.md)
- [Dynamic Values](tips/dynamicvalues.md)
- [XML](tips/xml.md)

61
docs/home/How-To.md Normal file
View File

@@ -0,0 +1,61 @@
# How-To
After downloading the project you can finally start creating your own program and use basalt. The first thing you want to use in your program is always:
```lua
local basalt = require("basalt")
```
It doesn't matter if you're using the source folder or the minified/packed version of basalt. Both can be found by using require("basalt") without .lua.
Also to really run basalt you should use
```lua
basalt.autoUpdate()
```
somewhere on the bottom of your program. basalt.autoUpdate() starts the event listener and the draw handler.
## Example
Here is a fully working example of how a program could look like:
```lua
local basalt = require("basalt") --> Load the basalt framework into the variable called "basalt"
--> Now we want to create a base frame, we call the variable "main" - by default everything you create is visible. (you don't need to use :show())
local main = basalt.createFrame()
local button = main:addButton() --> Here we add our first button
button:setPosition(4, 4) -- of course we want to change the default position of our button
button:setSize(16, 3) -- and the default size.
button:setText("Click me!") --> This method displays what the text of our button should look like
local function buttonClick() --> Let us create a function we want to call when the button gets clicked
basalt.debug("I got clicked!")
end
-- Now we just need to register the function to the buttons onClick event handlers, this is how we can achieve that:
button:onClick(buttonClick)
basalt.autoUpdate() -- As soon as we call basalt.autoUpdate, the event and draw handlers will listen to any incomming events (and draw if necessary)
```
If you're like us and strive for succinct and beautiful code, here is a cleaner implementation of the code above:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local button = main --> Basalt returns an instance of the object on most methods, to make use of "call-chaining"
:addButton() --> This is an example of call chaining
:setPosition(4,4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
end)
basalt.autoUpdate()
```

View File

@@ -1,92 +0,0 @@
## HowTo Use
To load the framework into your project, make use of the following code on top of your code.
```lua
local basalt = require("basalt")
```
It does not matter if you have installed the single file version or the full folder project. <br>
Both versions can be loaded by using `require("Basalt")`, you dont need to add `.lua`.
## Download
### Download the folder version
This version is for people who'd like to work with Basalt, change something in Basalt or checkout the project.<br>
But you are also able to just use it to create your own UI.<br>
To install the full project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P`
This will download the project as a folder called "Basalt". You are immediatly after the download is done able to use it in your projects.
### Download the single file version
This is the version you should use if you're done with programming. It is a little bit faster and it is also minified, which makes the project smaller.
To install the single filed project to your CC:Tweaked Computer, use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P packed`
This will download the project as a single file called "basalt.lua". You are immediatly after the download is done able to use it in your projects.
### Basalt Package Manager
The Basalt Package Manager is still in alpha!<br><br>
The Basalt Package Manager is a visual installer, you are able to change some settings, also to choose which objects are necessary for your projects and which are not.
To install the BPM (Basalt Package Manager) use the following command on your CC:Tweaked shell:
`pastebin run ESs1mg7P bpm true`
The true keyword in the end is optional and would simply start BPM immediately.
## Example
Here is a fully functioning example of Basalt code
```lua
local basalt = require("basalt") --> Load the Basalt framework
--> Create the first frame. Please note that Basalt needs at least one active "non-parent" frame to properly supply events
--> When Basalt#createFrame makes use of unique identifiers (commonly referred to as UIDs), meaning that the supplied value must be UNIQUE
local mainFrame = basalt.createFrame("mainFrame")
--> Show the frame to the user
mainFrame:show()
local button = mainFrame:addButton("clickableButton") --> Add a button to the mainFrame (With a unique identifier)
--> Set the position of the button, Button#setPosition follows an x, y pattern.
--> The x value is how far right the object should be from its anchor (negative values from an anchor will travel left)
--> The y value is how far down the object should be from its anchor (negative values from an anchor will travel up)
button:setPosition(4, 4)
button:setText("Click me!") --> Set the text of our button
local function buttonClick() --> This function serves as our click logic
basalt.debug("I got clicked!")
end
--> Remember! You cannot supply buttonClick(), that will only supply the result of the function
--> Make sure the button knows which function to call when it's clicked
button:onClick(buttonClick)
button:show() --> Make the button visible, so the user can click it
basalt.autoUpdate() --> Basalt#autoUpdate starts the event listener to detect user input
```
If you're like us and strive for succinct and beautiful code, here is a cleaner implementation of the code above:
```lua
local basalt = require("basalt")
local mainFrame = basalt.createFrame("mainFrame"):show()
local button = mainFrame --> Basalt returns an instance of the object on most methods, to make use of "call-chaining"
:addButton("clickableButton") --> This is an example of call chaining
:setPosition(4,4)
:setText("Click me!")
:onClick(
function()
basalt.debug("I got clicked!")
end)
:show()
basalt.autoUpdate()
```

36
docs/home/download.md Normal file
View File

@@ -0,0 +1,36 @@
Basalt provides multiple unique versions. A source version, a minified version and a web version.
## Source
This version is, like the name already says, the source code of basalt. If you want to dig into the code, add additional content or just prefer to use the source, then you should aim for the source-version.
The following command allows you to download the source-version on your computer:
`wget run https://basalt.madefor.cc/install.lua source [foldername] [branch]`
The first optional argument is the folder name you wish that basalt should be installed into, by default the folder is called basalt.
The second optional argument is the branch you want to use. If you don't know what this means please ignore it (the 2 options are master and dev)
## Minified / Packed
This version is the minified version, i also call it the packed version. There are 2 changes, the first one is that the code will be shown minified which makes the size much smaller, the second change is that you will recieve a file instead of a folder.
The following command allows you to download the packed-version on your computer:
`wget run https://basalt.madefor.cc/install.lua packed [filename] [branch]`
The first optional argument is the file name you wish that the installer should use, by default the file is called basalt.lua.
The second optional argument is the branch you want to use. If you don't know what this means please ignore it (the 2 options are master and dev)
## Web
The web version is a special version, used if your goal is to keep your project's size as small as possible. I suggest you to use the web version only if you don't restart your program over and over again. For example if you designed your program to reboot after the user made a bad choice (leads into a error or something like that) it is better to use the minified/source version.
The following command allows you to download the web-version on your computer:
`wget run https://basalt.madefor.cc/install.lua web [version] [filename]`
By default the first argument is the latest version of basalt's releases. [Here](https://github.com/Pyroxenium/Basalt/tree/master/docs/versions) you can see which versions are available to use.
For example: wget run https://basalt.madefor.cc/install.lua web basalt-1.6.3.lua - the second argument is just the file name, default is basaltWeb.lua.
Remember to rename `local basalt = require("basalt")` into `local basalt = require("basaltWeb")` if you want to use the web-version

View File

@@ -1,74 +0,0 @@
# Installer
This is just a script which helps you to setup your program to automatically install the Basalt UI Framework, if it doesn't exists. Means, you create your program (which requires basalt) and add this on the top of your program. Now, everytime you execute your program it checks if basalt.lua (or your custom filepath) exists or not, if not it installs it, or if you are using the advanced installer, it asks the user if the program is allowed to install basalt for you.
## Basic Installer
Here is a very basic one which just installs basalt.lua if don't exist:
```lua
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt
if not(fs.exists(filePath))then
shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", "")) -- this is an alternative to the wget command
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
```
## Advanced Installer
This is a visual version, it asks the user if he wants to install basalt.lua (if not found)<br>
![](https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/_media/installer.png)
```lua
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt
if not(fs.exists(filePath))then
local w,h = term.getSize()
term.clear()
local _installerWindow = window.create(term.current(),w/2-8,h/2-3,18,6)
_installerWindow.setBackgroundColor(colors.gray)
_installerWindow.setTextColor(colors.black)
_installerWindow.write(" Basalt Installer ")
_installerWindow.setBackgroundColor(colors.lightGray)
for line=2,6,1 do
_installerWindow.setCursorPos(1,line)
if(line==3)then
_installerWindow.write(" No Basalt found! ")
elseif(line==4)then
_installerWindow.write(" Install it? ")
elseif(line==6)then
_installerWindow.setTextColor(colors.black)
_installerWindow.setBackgroundColor(colors.gray)
_installerWindow.write("Install")
_installerWindow.setBackgroundColor(colors.lightGray)
_installerWindow.write(string.rep(" ",5))
_installerWindow.setBackgroundColor(colors.red)
_installerWindow.write("Cancel")
else
_installerWindow.write(string.rep(" ",18))
end
end
_installerWindow.setVisible(true)
_installerWindow.redraw()
while(not(fs.exists(filePath))) do
local event, p1,p2,p3,p4 = os.pullEvent()
if(event=="mouse_click")then
if(p3==math.floor(h/2+2))and(p2>=w/2-8)and(p2<=w/2-2)then
shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", ""))
_installerWindow.setVisible(false)
term.clear()
break
end
if(p3==math.floor(h/2+2))and(p2<=w/2+9)and(p2>=w/2+4)then
_installerWindow.clear()
_installerWindow.setVisible(false)
term.setCursorPos(1,1)
term.clear()
return
end
end
end
term.setCursorPos(1,1)
term.clear()
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
------------------------------
```

View File

@@ -33,22 +33,40 @@
</head>
<body>
<div id="app">Did you know: Basalt is a Pyroxene?></div>
<script src="//cdn.jsdelivr.net/npm/docsify-edit-on-github"></script>
<script>
window.$docsify = {
logo: '/_media/logo.png',
loadNavbar: true,
loadSidebar: true,
loadFooter: '_footer.md',
autoHeader: true,
subMaxLevel: 2,
subMaxLevel: 3,
homepage: 'Home.md',
name: 'Basalt',
repo: 'https://github.com/Pyroxenium/Basalt',
auto2top: true
auto2top: true,
search: {
maxAge: 86400000, // Expiration time, the default one day
paths: 'auto',
placeholder: 'Type to search',
noData: 'No Results!',
// Headline depth, 1 - 6
depth: 2,
hideOtherSidebarContent: false, // whether or not to hide other sidebar content
},
plugins: [
EditOnGithubPlugin.create("https://github.com/Pyroxenium/Basalt/blob/master/docs/", null, "Edit on Github")
]
}
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.28.0/components/prism-lua.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/@alertbox/docsify-footer/dist/docsify-footer.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
</body>
</html>

375
docs/install.lua Normal file
View File

@@ -0,0 +1,375 @@
-- this file can download the project or other tools from github
local args = table.pack(...)
local installer = {printStatus=true}
installer.githubPath = "https://raw.githubusercontent.com/Pyroxenium/Basalt/"
local function printStatus(...)
if(installer.printStatus)then
print(...)
elseif(type(installer.printStatus)=="function")then
installer.printStatus(...)
end
end
function installer.get(url)
local httpReq = http.get(url, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
printStatus("Downloading "..url)
if(httpReq~=nil)then
local content = httpReq.readAll()
if not content then
error("Could not connect to website")
end
return content
end
end
local basaltDataCache
function installer.getBasaltData()
if(basaltDataCache~=nil)then return basaltDataCache end
local content
printStatus("Downloading basalt data...")
if(fs.exists("basaltdata.json"))then
content = fs.open("basaltdata.json", "r")
else
content = installer.get("https://basalt.madefor.cc/basaltdata.json")
end
if(content~=nil)then
content = content.readAll()
basaltDataCache = textutils.unserializeJSON(content)
printStatus("Successfully downloaded basalt data!")
return basaltDataCache
end
end
-- Creates a filetree based on my github project, ofc you can use this in your projects if you'd like to
function installer.createTree(page, branch, dirName)
dirName = dirName or ""
printStatus("Receiving file tree for "..(dirName~="" and "Basalt/"..dirName or "Basalt"))
local tree = {}
local request = http.get(page, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
if not(page)then return end
if(request==nil)then error("API rate limit exceeded. It will be available again in one hour.") end
for _,v in pairs(textutils.unserialiseJSON(request.readAll()).tree)do
if(v.type=="blob")then
table.insert(tree, {name = v.path, path=fs.combine(dirName, v.path), url=installer.githubPath..branch.."/Basalt/"..fs.combine(dirName, v.path), size=v.size})
elseif(v.type=="tree")then
tree[v.path] = installer.createTree(v.url, branch, fs.combine(dirName, v.path))
end
end
return tree
end
function installer.createTreeByBasaltData(page, branch, dirName)
dirName = dirName or ""
printStatus("Receiving file tree for "..(dirName~="" and "Basalt/"..dirName or "Basalt"))
local bData = installer.getBasaltData()
if(bData~=nil)then
local tree = {}
for k,v in pairs(bData.structure)do
if(k=="base")then
for a,b in pairs(v)do
table.insert(tree, b)
end
else
tree[k] = v
end
end
return tree
end
end
local function splitString(str, sep)
if sep == nil then
sep = "%s"
end
local t={}
for v in string.gmatch(str, "([^"..sep.."]+)") do
table.insert(t, v)
end
return t
end
function installer.createIgnoreList(str)
local files = splitString(str, ":")
local ignList = {}
for k,v in pairs(files)do
local a = splitString(v, "/")
if(#a>1)then
if(ignList[a[1]]==nil)then ignList[a[1]] = {} end
table.insert(ignList[a[1]], a[2])
else
table.insert(ignList, v)
end
end
end
function installer.download(url, file)
local content = installer.get(url)
if(content~=nil)then
local f = fs.open(file, "w")
f.write(content)
f.close()
end
end
function installer.getRelease(version)
local v = installer.getBasaltData().versions[version]
if(v~=nil)then
printStatus("Downloading basalt "..version)
local content = http.get("https://basalt.madefor.cc/versions/"..v, {Authorization = _G._GIT_API_KEY and "token ".._G._GIT_API_KEY})
if(content~=nil)then
return content.readAll()
end
end
end
function installer.downloadRelease(version, file)
local content = installer.getRelease(version)
if(content~=nil)then
local f = fs.open(file or "basalt.lua", "w")
f.write(content)
f.close()
return true
end
return false
end
function installer.getPackedProject(branch, ignoreList)
if (ignoreList==nil)then
ignoreList = {"init.lua"}
else
table.insert(ignoreList, "init.lua")
end
local projTree = installer.createTree("https://api.github.com/repos/Pyroxenium/Basalt/git/trees/"..branch..":Basalt", branch, "")
local filteredList = {}
local project = {}
local function isInIgnoreList(file, ign)
if(ign~=nil)then
for k,v in pairs(ign)do
if(v==file.name)then
return true
end
end
end
return false
end
for k,v in pairs(projTree)do
if(type(k)=="string")then
for a,b in pairs(v)do
if not(isInIgnoreList(b, ignoreList~=nil and ignoreList[k] or nil))then
if(filteredList[k]==nil)then filteredList[k] = {} end
table.insert(filteredList[k], b)
end
end
else
if not(isInIgnoreList(v, ignoreList))then
table.insert(filteredList, v)
end
end
end
local fList = {}
local delay = 0
for k,v in pairs(filteredList)do
if(type(k)=="string")then
for a,b in pairs(v)do
table.insert(fList, function() sleep(delay)
if(project[k]==nil)then project[k] = {} end
table.insert(project[k], {content=installer.get(b.url), name=b.name, path=b.path, size = b.size, url = b.url})
delay = delay + 0.05
end)
end
else
table.insert(fList, function() sleep(delay) table.insert(project, {content=installer.get(v.url), name=v.name, path=v.path, size = v.size, url = v.url}) delay = delay + 0.05 end)
end
end
parallel.waitForAll(table.unpack(fList))
local projectContent =
[[
local project = {}
local packaged = true
local baseRequire = require
local require = function(path)
for k,v in pairs(project)do
if(type(v)=="table")then
for name,b in pairs(v)do
if(name==path)then
return b()
end
end
else
if(k==path)then
return v()
end
end
end
return baseRequire(path);
end
local getProject = function(subDir)
if(subDir~=nil)then
return project[subDir]
end
return project
end
]]
for k,v in pairs(project)do
if(type(k)=="string")then
local newSubDir = 'project["'..k..'"] = {}\n'
projectContent = projectContent.."\n"..newSubDir
for a,b in pairs(v)do
local newFile = 'project["'..k..'"]["'..b.name:gsub(".lua", "")..'"] = function(...)\n'..b.content..'\nend'
projectContent = projectContent.."\n"..newFile
end
else
local newFile = 'project["'..v.name:gsub(".lua", "")..'"] = function(...)\n'..v.content..'\nend'
projectContent = projectContent.."\n"..newFile
end
end
projectContent = projectContent..'\n return project["main"]()'
return projectContent
end
function installer.generateWebVersion(file, version)
if(fs.exists(file))then error("A file called "..file.." already exists!") end
version = version or "latest.lua"
local request = http.get("https://basalt.madefor.cc/versions/"..version, _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})
if(request~=nil)then
if(fs.exists(file))then
fs.delete(file)
end
local f = fs.open(file, "w")
local link = "https://basalt.madefor.cc/versions/"..version
local content = 'local request = http.get("'..link..'", _G._GIT_API_KEY and {Authorization = "token ".._G._GIT_API_KEY})\n'
content = content..
[[
if(request~=nil)then
return load(request.readAll())()
else
error("Unable to connect to ]]..link..[[")
end
]]
f.write(content)
f.close()
printStatus("Web version successfully downloaded!")
else
error("Version doesn't exist!")
end
end
function installer.getProjectFiles(branch, ignoreList)
local projTree = installer.createTree("https://api.github.com/repos/Pyroxenium/Basalt/git/trees/"..branch..":Basalt", branch, "")
local filteredList = {}
local project = {}
local function isInIgnoreList(file)
if(ignoreList~=nil)then
for k,v in pairs(ignoreList)do
if(v==file)then
return true
end
end
end
return false
end
for k,v in pairs(projTree)do
if not(isInIgnoreList(v.name))then
if(type(k)=="string")then
local sub = {}
for a,b in pairs(v)do
if not(isInIgnoreList(b.name))then
table.insert(sub, b)
end
end
filteredList[k] = sub
else
table.insert(filteredList, v)
end
end
end
local function downloadFile(url, path)
project[path] = installer.get(url)
end
local fList = {}
local delay = 0
for k,v in pairs(filteredList)do
if(type(k)=="string")then
for a,b in pairs(v)do
table.insert(fList, function() sleep(delay) downloadFile(b.url, b.path) end)
delay = delay + 0.05
end
else
table.insert(fList, function() sleep(delay) downloadFile(v.url, v.path) end)
delay = delay + 0.05
end
end
parallel.waitForAll(table.unpack(fList))
return project
end
function installer.downloadPacked(filename, branch, ignoreList, minify)
if(fs.exists(filename))then error("A file called "..filename.." already exists!") end
local projectContent = installer.getPackedProject(branch, ignoreList)
if(minify)then
local min
if(fs.exists("packager.lua"))then
min = require("packager")
else
min = load(installer.get("https://raw.githubusercontent.com/Pyroxenium/Basalt/master/docs/packager.lua"))()
end
if(min~=nil)then
success, data = min(projectContent)
if(success)then
projectContent = data
else
error(data)
end
end
end
local f = fs.open(filename, "w")
f.write(projectContent)
f.close()
printStatus("Packed version successfully downloaded!")
end
function installer.downloadProject(projectDir, branch, ignoreList)
if(fs.exists(projectDir))then error("A folder called "..projectDir.." already exists!") end
projectDir = projectDir or "basalt"
branch = branch or "master"
local projectFiles = installer.getProjectFiles(branch, ignoreList)
fs.makeDir(projectDir)
for k,v in pairs(projectFiles)do
local f = fs.open(fs.combine(projectDir, k), "w")
f.write(v)
f.close()
end
printStatus("Source version successfully downloaded!")
end
if(#args>0)then
if(string.lower(args[1])=="bpm")or(string.lower(args[1])=="basaltpackagemanager")or(string.lower(args[1])=="gui")then
installer.download("https://raw.githubusercontent.com/Pyroxenium/Basalt/master/basaltPackageManager.lua", "basaltPackageManager.lua")
if(args[2]=="true")then shell.run("basaltPackageManager.lua") fs.delete("basaltPackageManager.lua") end
elseif(string.lower(args[1])=="packed")then
installer.downloadPacked(args[2] or "basalt.lua", args[3] or "master", args[4]~=nil and installer.createIgnoreList(args[4]) or nil, args[5] == "false" and false or true)
elseif(string.lower(args[1])=="source")then
installer.downloadProject(args[2] or "basalt", args[3] or "master", args[4]~=nil and installer.createIgnoreList(args[4]) or nil)
elseif(string.lower(args[1])=="web")then
installer.generateWebVersion(args[3] or "basaltWeb.lua", args[2] or "latest.lua")
elseif(string.lower(args[1])=="file")or(string.lower(args[1])=="release")then
installer.download("https://basalt.madefor.cc/versions/"..args[2] or "latest.lua", args[3] or "basalt.lua")
end
end
return installer

View File

@@ -1,487 +0,0 @@
--Basalt configurated installer
local filePath = "basalt.lua" --here you can change the file path default: basalt
if not(fs.exists(filePath))then
shell.run("pastebin run ESs1mg7P packed true "..filePath:gsub(".lua", "")) -- this is an alternative to the wget command
end
local basalt = require(filePath:gsub(".lua", "")) -- here you can change the variablename in any variablename you want default: basalt
local maxCoWorker = 3
local recipeList = {}
local craftingQueue = {}
local bridge = peripheral.find("rsBridge")
local w, h = term.getSize()
local main = basalt.createFrame()
local home = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):setSize(w, h-2)
local recipes = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):hide()
local log = main:addFrame():setPosition(1,2):setBackground(colors.lightGray):hide()
local menuBar = main:addMenubar():addItem("Home"):addItem("Recipes"):addItem("Log"):setBackground(colors.gray):setSize(w, 1):setSpace(6):setScrollable():show()
menuBar:onChange(function(self)
home:hide()
recipes:hide()
log:hide()
if(self:getValue().text=="Home")then
home:show()
elseif(self:getValue().text=="Recipes")then
recipes:show()
elseif(self:getValue().text=="Log")then
log:show()
end
end)
local function buttonVisuals(btn)
btn:onClick(basalt.schedule(function() btn:setBackground(colors.black) btn:setForeground(colors.lightGray) os.sleep(0.1) btn:setBackground(colors.gray) btn:setForeground(colors.black) end))
end
local coworkerCount = home:addLabel():setText(maxCoWorker):setPosition(45,2):show()
home:addLabel():setText("Co-Worker:"):setPosition(32,2):show()
buttonVisuals(home:addButton():setText(">"):setSize(1,1):setPosition(47,2):onClick(function() if(maxCoWorker<100)then maxCoWorker = maxCoWorker+1 end coworkerCount:setText(maxCoWorker) end):show())
buttonVisuals(home:addButton():setText("<"):setSize(1,1):setPosition(43,2):onClick(function() if(maxCoWorker>1)then maxCoWorker = maxCoWorker-1 end coworkerCount:setText(maxCoWorker) end):show())
local logList = log:addList():setPosition(2,2):setSize(w-2,h-3):setScrollable(false):show()
local jobList = home:addList():setPosition(20,4):setSize(30,10):show()
local rList = recipes:addList():setPosition(13,2):setSize(38,16):show()
local function logging(text)
logList:addItem(text)
if(logList:getItemCount()>h-3)then
logList:removeItem(1)
end
end
logging("Loading autocrafter...")
function SaveToFile()
local file = io.open("recipes", "wb")
local sel = rList:getItemIndex()
rList:clear()
for _,v in pairs(recipeList)do
if(v.useDmg)then
file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|true|", "\n")
else
file:write(v.name.."|"..v.damage.."|"..v.minAmount.."|"..v.maxCraftAmount.."|false|", "\n")
end
rList:addItem(v.minAmount.."x "..v.name..":"..v.damage, nil, nil, v)
end
rList:selectItem(sel)
file:close()
end
buttonVisuals(recipes:addButton():setPosition(2,2):setText("Remove"):setSize(8,1):onClick(function()
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
table.remove(recipeList, k)
logging("Removed recipe: "..v.name..":"..v.damage)
SaveToFile()
end
end
end
end))
local changeAmn = recipes:addInput():setPosition(4,4):setSize(5,1):setInputType("number"):setForeground(colors.black):setDefaultText("32", colors.black):onChange(function(self)
local val = tonumber(self:getValue()) or 32
if(val<0)then
self:setValue(0)
end
end)
buttonVisuals(recipes:addButton():setPosition(2,4):setSize(1,1):setText("-"):onClick(function()
local val = tonumber(changeAmn:getValue()) or 32
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
v.minAmount = v.minAmount - val
if(v.minAmount < 0)then v.minAmount = 0 end
SaveToFile()
end
end
end
end
end))
buttonVisuals(recipes:addButton():setPosition(10,4):setSize(1,1):setText("+"):onClick(function()
local val = tonumber(changeAmn:getValue()) or 32
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
v.minAmount = v.minAmount + val
SaveToFile()
end
end
end
end
end))
buttonVisuals(recipes:addButton():setPosition(2,6):setSize(8,1):setText("Set"):onClick(function()
local val = tonumber(changeAmn:getValue()) or 32
if(rList:getValue()~=nil)then
local sel = rList:getValue().args[1]
if(val>0)and(sel.name~=nil)and(sel.damage~=nil)then
for k,v in pairs(recipeList)do
if(v.name==sel.name)and(tonumber(v.damage)==tonumber(sel.damage))then
v.minAmount = val
SaveToFile()
end
end
end
end
end))
local rItemFrame = home:addFrame():setPosition(7,3):setBackground(colors.gray):setSize(27,6):setMoveable(true):setBar("Remove Item", colors.black, colors.lightGray):showBar():hide()
rItemFrame:addButton():setPosition(1,1):setAnchor("topRight"):setSize(1,1):setBackground(colors.black):setForeground(colors.lightGray):setText("x"):onClick(function() rItemFrame:hide() end):show()
rItemFrame:addLabel():setText("Item ID:"):setPosition(2,3):show()
local ritemId = rItemFrame:addInput("itemid"):setPosition(12,3):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("minecraft:stick", colors.gray):show()
rItemFrame:addButton():setPosition(-7,0):setAnchor("bottomRight"):setSize(8,1):setBackground(colors.black):setForeground(colors.lightGray):setText("Remove"):onClick(function()
local id = ritemId:getValue()
for k,v in pairs(recipeList)do
if(v.name==id)then
table.remove(recipeList, k)
logging("Removed recipe: "..v.name..":"..v.damage)
end
end
SaveToFile()
end)
local aItemFrame = home:addFrame():setPosition(7,3):setBackground(colors.gray):setSize(27,12):setMoveable(true):setBar("Add Item", colors.black, colors.lightGray):showBar():hide()
aItemFrame:addLabel():setText("Item ID:"):setPosition(2,3)
aItemFrame:addLabel():setText("Damage:"):setPosition(2,5)
aItemFrame:addLabel():setText("Count:"):setPosition(2,7)
aItemFrame:addLabel():setText("Max:"):setPosition(2,9)
aItemFrame:addLabel():setText("Use Damage:"):setAnchor("bottomLeft"):setPosition(4,0)
local itemId = aItemFrame:addInput():setPosition(12,3):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setDefaultText("minecraft:stick", colors.gray)
local itemDamage = aItemFrame:addInput():setPosition(12,5):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("0", colors.gray)
local itemCount = aItemFrame:addInput():setPosition(12,7):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("64", colors.gray)
local itemMaxCount = aItemFrame:addInput():setPosition(12,9):setSize(15,1):setBackground(colors.black):setForeground(colors.lightGray):setInputType("number"):setDefaultText("0", colors.gray)
local useDamage = aItemFrame:addCheckbox():setAnchor("bottomLeft"):setPosition(2,0):setBackground(colors.black):setForeground(colors.lightGray):setValue(true)
aItemFrame:addButton():setAnchor("topRight"):setPosition(1,1):setSize(1,1):setBackground(colors.black):setForeground(colors.lightGray):setText("x"):onClick(function() aItemFrame:hide() end)
aItemFrame:addButton():setAnchor("bottomRight"):setPosition(-4,0):setSize(5,1):setBackground(colors.black):setForeground(colors.lightGray):setText("Add"):onClick(function()
local id = itemId:getValue()
local dmg = itemDamage:getValue() == "" and 0 or itemDamage:getValue()
local count = itemCount:getValue() == "" and 64 or itemCount:getValue()
local maxCount = itemMaxCount:getValue() == "" and 0 or itemMaxCount:getValue()
local usedamage = useDamage:getValue() or true
if(id~="")then
local itemExist = false
for k,v in pairs(recipeList)do
if(v.name==id)then
if(usedamage)then
if(v.damage==dmg)then
itemExist = true
v.minAmount = count or 64
v.maxCraftAmount = maxCount or 0
logging("Edited recipe: "..(count).."x "..id..":"..dmg)
end
else
itemExist = true
v.minAmount = count or 64
v.maxCraftAmount = maxCount or 0
logging("Edited recipe: "..(count).."x "..id..":"..dmg)
end
end
end
if(itemExist == false)then
table.insert(recipeList, {name = id, damage = dmg or 0, minAmount = count, maxCraftAmount = maxCount or 0, useDmg = usedamage, fails = 0, timer = 0})
logging("Added recipe: "..(count).."x "..id..":"..dmg)
end
SaveToFile()
else
logging("Please set a ID.")
end
end)
buttonVisuals(home:addButton():setText("Add Item"):setSize(12,3):setPosition(2,6):onClick(function() aItemFrame:show() aItemFrame:setFocus() end):show())
buttonVisuals(home:addButton():setText("Remove Item"):setSize(12,3):setPosition(2,10):onClick(function() rItemFrame:show() rItemFrame:setFocus() end):show())
local function StringSeperate(str, seperator)
local words = {}
local word = ""
if(string.sub(str, str:len(), str:len())~=seperator)then
str = str..""..seperator
end
for x=1,str:len() do
local s = string.sub(str,x,x)
if(s==seperator)then
table.insert(words, word)
word = ""
else
word = word..s
end
end
return words
end
if not(fs.exists("recipes"))then
fs.open("recipes","w").close()
end
local f = fs.open("recipes", "r")
for line in f.readLine do
local tab = StringSeperate(line, "|")
if(tab[1]~=nil)and(tab[2]~=nil)and(tab[3]~=nil)and(tab[4]~=nil)and(tab[5]~=nil)then
logging("Registered recipe: "..tab[3].."x "..tab[1]..":"..tab[2])
local recipe = {name=tab[1],damage=tonumber(tab[2]),minAmount=tonumber(tab[3]),maxCraftAmount=tonumber(tab[4]),fails=0,timer=0}
if(tab[5]=="true")then
recipe.useDmg=true
else
recipe.useDmg=false
end
rList:addItem(recipe.minAmount.."x "..recipe.name..":"..recipe.damage, nil, nil, recipe)
table.insert(recipeList, recipe)
end
end
f.close()
local function findKeyWithItemName(table, itemname, damage)
for k,v in pairs(table)do
if(v.name==itemname)and(v.damage == damage)then
return k
end
end
return nil
end
local scanChestBtn = home:addButton("scanChest"):setText("Scan Chest"):setSize(12,3):setPosition(2,2):show()
local function checkChestForNewEntrys()
scanChestBtn:setText("Scanning..")
local inventory = peripheral.find("minecraft:chest")
local items = {}
local itemAmounts = {}
local somethingChanged = false
if(inventory~=nil)then
for x=1,inventory.size(), 1 do
local item = inventory.getItemDetail(x)
if(item~=nil)then
if(item.damage==nil)then item.damage = 0 end
table.insert(items, item)
end
os.sleep(0.1)
end
else
logging("No chest available!")
end
if(#items > 0)then
for _,v in pairs(items)do
local key = findKeyWithItemName(itemAmounts, v.name, v.damage)
if(key~=nil)then
itemAmounts[key].count = itemAmounts[key].count + v.count
else
table.insert( itemAmounts, {name=v.name, damage=v.damage, count = v.count})
end
end
end
if(#itemAmounts > 0)then
for _,v in pairs(itemAmounts)do
local key = findKeyWithItemName(recipeList, v.name, v.damage)
if(key~=nil)then
if(recipeList[key].minAmount ~= v.count)then
logging("Edited recipe: "..v.name.. ":"..v.damage.." new count: "..v.count)
end
somethingChanged = true
recipeList[key].minAmount = v.count
else
table.insert( recipeList, {name=v.name, damage=v.damage, minAmount = v.count, maxCraftAmount = 0, useDmg = true, fails = 0, timer = 0})
somethingChanged = true
logging("Registered recipe: "..v.count.."x "..v.name.. ":"..v.damage)
end
end
if(somethingChanged)then
SaveToFile()
end
end
scanChestBtn:setText("Scan Chest")
logging("Scanning chest done.")
end
local chestScanThread = main:addThread("chestScanThread")
buttonVisuals(scanChestBtn:onClick(function() chestScanThread:start(checkChestForNewEntrys) end))
local function GetAmount(itemAmount, recipe)
local amount = 0
if(itemAmount < recipe.minAmount)then
if(recipe.maxCraftAmount > 0)then
if(recipe.minAmount-itemAmount > recipe.maxCraftAmount)then
amount = recipe.maxCraftAmount
else
amount = recipe.minAmount-itemAmount
end
else
amount = recipe.minAmount-itemAmount
end
end
return amount
end
function GetRecipeKey(pattern)
for k,v in pairs(recipeList)do
if(v.name == pattern.name)then
if(pattern.damage==nil)then return k end
if(v.useDmg)then
if(v.damage == pattern.damage)then
return k
end
else
return k
end
end
end
return nil
end
local function CheckCraftingRecipe(recipe)
local pattern = bridge.getItem({name=recipe.name})
local item = {pattern=pattern, amount=0}
if(pattern~=nil)then
local storedAmount = pattern.amount
local neededItemAmount = GetAmount(storedAmount, recipe)
if(neededItemAmount > 0)then
item.amount = neededItemAmount
table.insert(craftingQueue, item)
return true
end
end
return false
end
function RemoveRecipe(item)
local key = -1
for k,v in pairs(recipeList)do
if(v.name == item.name)and(v.damage== item.damage)then
key = k
end
end
if(key>=0)then
table.remove(recipeList, key)
end
SaveToFile()
end
local function FindKeyInTable(table, item)
for k,v in pairs(table)do
if(v==item)then
return k
end
end
return nil
end
local function CheckAllRecipes()
for _,v in pairs(recipeList)do
if(type(v)=="table")then
CheckCraftingRecipe(v)
end
end
end
local function jobCrafting(coworker, item)
if(jobList:getItem(coworker)~=nil)then
jobList:editItem(coworker, "Co-Worker "..coworker..": "..item.amountToCraft.."x "..item.item.displayName:gsub(" ", ""))
else
jobList:addItem("Co-Worker "..coworker..": "..item.amountToCraft.."x "..item.item.displayName:gsub(" ", ""))
end
end
local function jobDone(coworker)
if(jobList:getItem(coworker)~=nil)then
jobList:editItem(coworker, "Co-Worker "..coworker..": waiting...")
else
jobList:addItem("Co-Worker "..coworker..": waiting...")
end
end
local coWorkerId = 1
local function UpdateCraftingQueue()
while(#craftingQueue > 0)do
local activeCoWorkers = {}
local craftingQueuesToRemove = {}
for _,v in pairs(craftingQueue)do
if(#activeCoWorkers+1 <= maxCoWorker)then
local stack = v.pattern
local recipeKey = GetRecipeKey(stack)
local waittimer = 0
local multiplier = 1
if(recipeList[recipeKey].fails > 0)and(recipeList[recipeKey].fails <=10)then
multiplier = recipeList[recipeKey].fails
elseif(recipeList[recipeKey].fails > 10)then
multiplier = 20
end
waittimer = multiplier * 30
if(os.clock()>=recipeList[recipeKey].timer+waittimer)then
if not(bridge.isItemCrafting(stack.name))then
local currentItemState = {item=stack, curAmount = stack.count, amountToCraft = v.amount}
if(bridge.isItemCraftable({name=stack.name}))then
local task, errormsg = bridge.craftItem({name=stack.name, count = v.amount})
if(task)then
logging("Sheduled Task: "..v.amount.." ("..stack.name..") "..stack.displayName:gsub(" ", ""))
jobCrafting(coWorkerId, currentItemState)
currentItemState.coWorker = coWorkerId
coWorkerId = coWorkerId + 1
if(coWorkerId > maxCoWorker)then coWorkerId = 1 end
table.insert(activeCoWorkers, currentItemState)
recipeList[recipeKey].fails = 0
else
logging("Error sheduling task: "..v.amount.."x ("..stack.name..") "..stack.displayName:gsub(" ", ""))
logging("Not enough materials!")
recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1
recipeList[recipeKey].timer = os.clock()
end
else
logging("Error sheduling task: "..v.amount.."x ("..stack.name..") "..stack.displayName:gsub(" ", ""))
logging("No pattern available!")
recipeList[recipeKey].fails = recipeList[recipeKey].fails + 1
recipeList[recipeKey].timer = os.clock()
end
end
end
table.insert(craftingQueuesToRemove, v)
end
end
if(#craftingQueuesToRemove > 0)then
for _,v in pairs(craftingQueuesToRemove)do
local id = FindKeyInTable(craftingQueue, v)
table.remove(craftingQueue, id)
end
end
while(#activeCoWorkers > 0)do
local finishedCoworker = {}
for _,v in pairs(activeCoWorkers)do
if not(bridge.isItemCrafting(v.item.name))then
logging("Task done: "..v.amountToCraft.."x ("..v.item.name..") "..v.item.displayName:gsub(" ", ""))
table.insert(finishedCoworker, v)
end
end
if(#finishedCoworker>0)then
for _,v in pairs(finishedCoworker)do
local id = FindKeyInTable(activeCoWorkers, v)
table.remove(activeCoWorkers, id)
jobDone(v.coWorker)
end
end
os.sleep(0.75)
end
os.sleep(0.75)
end
end
main:addThread("craftingThread"):start(function() while true do CheckAllRecipes() os.sleep(1) UpdateCraftingQueue() os.sleep(1) end end)
logging("Autocrafter successfully loaded!")
basalt.autoUpdate()

View File

@@ -1,4 +1,12 @@
With animations, you can create a beautiful experience for users while interacting with your program.<br>
With animations, you can create a beautiful experience for users while interacting with your program.
There are 2 types of animations, predefined animations and custom animations. By using add and wait you can create custom
animations (calls). Pre-defined methods are for example move, offset, size, changeText,...
:setObject always sets the object on what pre-defined methods should apply on.
When calling a pre-defined animation it will check what is safed as object (:setObject) and will calculate the animation methods based on that which means you won't
be able to change the object on the fly - you will always have to recreate the animation itself
| | |
|---|---|
@@ -6,6 +14,8 @@ With animations, you can create a beautiful experience for users while interacti
|[wait](objects/Animation/wait.md)|Adds a amount to the animation time
|[play](objects/Animation/play.md)|Plays the animation
|[cancel](objects/Animation/cancel.md)|Cancels the animation
|[addMode](objects/Animation/addMode.md)|Adds custom easings
|[setMode](objects/Animation/setMode.md)|Changes the current easing-calculation
|[setObject](objects/Animation/setObject.md)|Sets an object on which predefined animations should work on
|[move](objects/Animation/move.md)|Predefined animation: moves the object to a new position
|[offset](objects/Animation/offset.md)|Predefined animation: Changes the offset of that object
@@ -18,4 +28,5 @@ With animations, you can create a beautiful experience for users while interacti
| | |
|---|---|
|[onStart](objects/Animation/onStart.md)|Gets called as soon as the animation is started
|[onDone](objects/Animation/onDone.md)|Gets called as soon as the animation has finished

View File

@@ -0,0 +1,30 @@
## addMode
Adds a new easing curve into the available easing list. Checkout the animation object if you want to know how this works.
#### Parameters:
1. `string` - The name of the curve you want to use.
2. `functon` - The function to call
#### Returns:
1. `animation` Animation in use
#### Usage:
* Creates a new curve
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton)
local function easeInBack(t) -- t is the time from 0 to 1
local c1 = 1.70158;
local c3 = c1 + 1
return c3*t^3-c1*t^2
end
aAnimation:addMode("coolEaseInBack", easeInBack)
aAnimation:setMode("coolEaseInBack"):move(15,3,2):play()
```

View File

@@ -2,9 +2,9 @@
Changes the background color while the animation is running
#### Parameters:
1. `table` multiple color numbers - example: {colors.red, colors.yellow, colors.green}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
1. `number` duration in seconds
2. `number` time - time when this part should begin (offset to when the animation starts - default 0)
3. `...` multiple color numbers - example: colors.red, colors.yellow, colors.green
#### Returns:
1. `animation` Animation in use

View File

@@ -3,8 +3,10 @@ Changes the text while animation is running
#### Parameters:
1. `table` multiple text strings - example: {"i", "am", "groot"}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
1. `number` duration in seconds
2. `number` time - time when this part should begin (offset to when the animation starts - default 0)
3. `...` multiple text strings - example: "i", "am", "groot"
#### Returns:
1. `animation` Animation in use

View File

@@ -2,9 +2,9 @@
Changes the text color while the animation is running
#### Parameters:
1. `table` multiple color numbers - example: {colors.red, colors.yellow, colors.green}
2. `number` duration in seconds
3. `number` time - time when this part should begin (offset to when the animation starts - default 0)
1. `number` duration in seconds
2. `number` time - time when this part should begin (offset to when the animation starts - default 0)
1. `...` multiple color numbers - example: colors.red, colors.yellow, colors.green
#### Returns:
1. `animation` Animation in use

View File

@@ -0,0 +1,16 @@
## onStart
`onStart(self)`<br>
This is a event which gets fired as soon as the animation is started.
```lua
local basalt = require("Basalt")
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):changeTextColor({colors.red, colors.yellow, colors.green}, 2)
aAnimation:onStart(function()
basalt.debug("The animation is started")
end)
aAnimation:play()
```

View File

@@ -0,0 +1,36 @@
## setMode
Changes the easing curve. If you want to test them, here is a interesting website: https://easings.co
#### Parameters:
1. `string` - The name of the curve you want to use.
#### Returns:
1. `animation` Animation in use
#### Usage:
* Takes 2 seconds to move the object from its current position to x15 y3
```lua
local mainFrame = basalt.createFrame()
local testButton = mainFrame:addButton("buttonToAnimate")
local aAnimation = mainFrame:addAnimation():setObject(testButton):setMode("easeInBounce"):move(15,3,2):play()
```
## Easing Curve List
Here is a list of all available easing curves:
| | | |
|---|---|---|
|linear||
|easIn|easeOut|easeInOut
|easeInSine|easeOutSine|easeInOutSine
|easeInBack|easeOutBack|easeInOutBack
|easeInCubic|easeOutCubic|easeInOutCubic
|easeInElastic|easeOutElastic|easeInOutElastic
|easeInExpo|easeOutExpo|easeInOutExpo
|easeInBack|easeOutBack|easeInOutBack
|easeInQuad|easeOutQuad|easeInOutQuad
|easeInQuint|easeOutQuint|easeInOutQuint
|easeInQuart|easeOutQuart|easeInOutQuart
|easeInCirc|easeOutCirc|easeInOutCirc
|easeInBounce|easeOutBounce|easeInOutBounce

View File

@@ -1,37 +1,48 @@
# Basalt
This is the UI Manager and the first thing you want to access.
Before you can access Basalt, you need to add the following code on top of your file:
`local basalt = require("basalt")`
```lua
local basalt = require("basalt")
```
require loads the UI Framework into your project.
Now you are able to access the following list of methods:
What this code does is it loads basalt into the basalt variable.
You are now able to access the following list of methods:
| | |
|---|---|
|[autoUpdate](objects/Basalt/autoUpdate.md)|Starts the event and draw listener
|[createFrame](objects/Basalt/createFrame.md)|Creates a new base frame
|[removeFrame](objects/Basalt/removeFrame.md)|Removes a previously created base frame
|[debug](objects/Basalt/debug.md)|Writes something into the debug console
|[getFrame](objects/Basalt/getFrame.md)|Returns a frame object by it's id
|[getActiveFrame](objects/Basalt/getActiveFrame.md)|Returns the currently active base frame
|[autoUpdate](objects/Basalt/autoUpdate.md)|Starts the event and draw listener
|[update](objects/Basalt/update.md)|Starts the event and draw listener once
|[stopUpdate](objects/Basalt/stopUpdate.md)|Stops the currently active event and draw listener
|[getTheme](objects/Basalt/getTheme.md)|Returns the currently active theme
|[getVariable](objects/Basalt/getVariable.md)|Returns a variable defined with setVariable
|[getVersion](objects/Basalt/getVersion.md)|Returns the Basalt version
|[isKeyDown](objects/Basalt/isKeyDown.md)|Returns if the key is held down
|[debug](objects/Basalt/debug.md)|Writes something into the debug console
|[log](objects/Basalt/log.md)|Writes something into the log file
|[setTheme](objects/Basalt/setTheme.md)|Changes the base theme of basalt
|[setVariable](objects/Basalt/setVariable.md)|Sets a variable which you can access via XML
|[onEvent](objects/Basalt/onEvent.md)|Event listener
|[removeFrame](objects/Basalt/removeFrame.md)|Removes a previously created base frame
|[schedule](objects/Basalt/schedule.md)|Schedules a new task
|[setActiveFrame](objects/Basalt/setActiveFrame.md)|Sets the active frame
|[setTheme](objects/Basalt/setTheme.md)|Changes the base theme of basalt
|[setMouseDragThrottle](objects/Basalt/setMouseDragThrottle.md)|Changes the mouse drag throttle amount
|[setMouseMoveThrottle](objects/Basalt/setMouseMoveThrottle.md)|CraftOS-PC: Changes the mouse move throttle amount
|[setVariable](objects/Basalt/setVariable.md)|Sets a variable which you can access via XML
|[stopUpdate / stop](objects/Basalt/stopUpdate.md)|Stops the currently active event and draw listener
|[update](objects/Basalt/update.md)|Starts the event and draw listener once
# Examples
## Examples
Here is a lua example on how to create a empty base frame and start basalt's listener.
```lua
local basalt = require("basalt") -- we load the UI Framework into our project
local basalt = require("basalt") -- Loads Basalt into our project
local main = basalt.createFrame() -- we create a base frame - on that frame we are able to add object's
local main = basalt.createFrame() -- Creates a base frame. On that frame we are able to add object's
-- here we would add additional object's
-- Here we would add additional object's
basalt.autoUpdate() -- we start listening to incoming events and draw stuff on the screen
```
basalt.autoUpdate() -- Starts listening to incoming events and draw stuff on the screen. This should nearly always be the last line.
```

View File

@@ -1,12 +1,18 @@
## basalt.autoUpdate
# Basalt
## autoUpdate
This starts the event and draw handler for you. The listeners will run until you stop them.
#### Parameters:
1. `boolean` optional - if you use false as the first parameter it would stop the listeners.
### Parameters
1. `boolean` optional - if you use false as the first parameter it would stop the listeners. Using false is a synonym for [`basalt.stopUpdate()`](objects/Basalt/stopUpdate.md).
### Usage
* Enables the basalt listeners, otherwise the screen will not continue to update
#### Usage:
* Enable the basalt listeners, otherwise the screen will not continue to update
```lua
local main = basalt.createFrame()
basalt.autoUpdate()
```
```

View File

@@ -1,17 +1,24 @@
## basalt.createFrame
# Basalt
## createFrame
Creates a new base-frame, you can have as many base-frames as you want, but only 1 can be active (visible) at the same time.
You can always switch between your base frames.
Only the currently active base-frame listens to incoming events (except for some events like time-events and peripheral-events)
#### Parameters:
### Parameters
1. `string` id - optional (if you dont set a id it will automatically create a uuid for you)
#### Returns:
### Returns
1. `frame` object
#### Usage:
### Usage
* How to use multiple base frames:
```lua
local main1 = basalt.createFrame() -- Visible base frame on program start
local main2 = basalt.createFrame()
@@ -24,4 +31,5 @@ main1:addButton()
end)
main2:addLabel()
:setText("We are currently on main2")
```
basalt.autoUpdate()
```

View File

@@ -1,22 +1,29 @@
## basalt.debug
# Basalt
## debug
Creates a label with some information on the main frame on the bottom left. When you click on that label it will open a log view for you. See it as the new print for debugging
You can also edit the default debug Label (change position, change color or whatever you want) by accessing the variable basalt.debugLabel
You can also edit the default debug Label (change position, change color or whatever you want) by accessing the variable `basalt.debugLabel`
which returns the debug Label.
Also basalt.debugFrame and basalt.debugList are available.
`basalt.debugFrame` and `basalt.debugList` are also available.
### Parameters
#### Parameters:
1. `...` (multiple parameters are possible, like print does)
#### Usage:
### Usage
* Prints "Hello! ^-^" to the debug console
```lua
basalt.debug("Hello! ", "^-^")
```
* Changes the debug label's anchor
```lua
basalt.debugLabel:setAnchor("topLeft") -- default anchor is bottomLeft
basalt.debug("Hello!")
```
```

View File

@@ -1,12 +1,18 @@
## basalt.getActiveFrame
Returns the currently active/visible base frame
# Basalt
## getActiveFrame
Returns the currently active/visible base frame.
### Returns
#### Returns:
1. `frame` The current frame
#### Usage:
### Usage
* Displays the active frame name in the debug console
```lua
local main = basalt.createFrame()
basalt.debug(basalt.getActiveFrame():getName()) -- returns the id
```
```

View File

@@ -1,14 +1,21 @@
## basalt.getFrame
Returns a base frame by the given id
# Basalt
## getFrame
Returns a base frame by the given id.
### Parameters
#### Parameters:
1. `string` id
#### Returns:
1. `frame` object
### Returns
1. `frame` The frame with the supplied id.
### Usage
#### Usage:
* Creates, fetches and shows the "myFirstFrame" object
```lua
local main = basalt.createFrame("firstBaseFrame")
local main2 = basalt.createFrame("secondBaseFrame")
@@ -16,8 +23,9 @@ main:addButton()
:setText("Show")
:onClick(function()
local frame2 = basalt.getFrame("secondBaseFrame")
if(frame2~=nil)then
if(frame2 ~= nil)then
frame2:show()
end
end)
```
basalt.autoUpdate()
```

View File

@@ -0,0 +1,18 @@
# Basalt
## basalt.getTheme
Returns the current base-theme. This base-theme can be set using setTheme.md.
A list of base-theme keys can be found [here](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua).
### Returns
1. `number` The color of the requested base-theme key.
### Usage
* Displays the color of the main background in the debug console
```lua
basalt.debug(basalt.getTheme("BasaltBG"))
```

View File

@@ -0,0 +1,26 @@
# Basalt
## getVariable
Returns a variable defined with [setVariable](objects/Basalt/setVariable)
### Returns
1. `variable` The variable stored
### Usage
* Displays the stored variable in the debug console
```lua
basalt.setVariable("abc", function()
basalt.debug("I got clicked")
return 1
end)
basalt.debug(basalt.getVariable("abc")()) -- Should debug log "I got clicked" and debug log 1 (which was returned from the function)
```
```xml
<button onClick="abc" text="Click me" />
```

View File

@@ -0,0 +1,17 @@
# Basalt
## getVersion
Returns the currently active/visible base frame.
### Returns
1. `string` The current version of Basalt
### Usage
* Displays the version of Basalt in the debug console
```lua
basalt.debug(basalt.getVersion()) -- Example: 1.6.2
```

View File

@@ -1,14 +1,21 @@
## basalt.isKeyDown
# Basalt
## isKeyDown
Checks if the user is currently holding a key
#### Parameters:
1. `number` key code (use the keys table for that)
### Parameters
1. `number` key code (use the [keys table](https://tweaked.cc/module/keys.html) for that)
### Returns
#### Returns:
1. `boolean` true or false
#### Usage:
### Usage
* Shows a debug message with true or false if the left ctrl key is down, as soon as you click on the button.
```lua
local main = basalt.createFrame()
local aButton = mainFrame:addButton()
@@ -18,4 +25,4 @@ local aButton = mainFrame:addButton()
basalt.debug(basalt.isKeyDown(keys.leftCtrl))
end)
basalt.autoUpdate()
```
```

View File

@@ -1,15 +1,28 @@
## basalt.log
This writes something into a file. The main goal is to make debugging errors easier. Lets say you'r program is crashing and
you don't know why, you could use basalt.log
# Basalt
The log files will automatically removed after you start your program again
## log
This writes something into a file. The main goal is to make debugging errors easier. Lets say you'r program is crashing and you don't know why, you could use basalt.log The log files will automatically removed after you start your program again.
### Parameters
#### Parameters:
1. `string` The text to write into the log file
2. `string` - optional (default: "Debug") - the type to write
#### Usage:
### Usage
* Writes "Hello!" into the log file
```lua
basalt.log("Hello!")
```
This should result in there beeing a file called `basaltLog.txt`. In the file it should say `[Basalt][Debug]: Hello!`.
* Writes "Config file missing" into the log file, with warning as prefix.
```lua
basalt.log("Config file is missing", "WARNING")
```
This should result in there beeing a file called `basaltLog.txt`. In the file it should say `[Basalt][WARNING]: Config file is missing`.

View File

@@ -0,0 +1,21 @@
# Basalt
## onEvent
This is the top-level method to intercept an event before sending it to the object event handlers. If you use return false, the event is not passed to the event handlers.
### Parameters
1. `function` The function which should be called
### Usage
```lua
local basalt = require("basalt")
basalt.onEvent(function(event)
if(event=="terminate")then
return false
end
end)
```

View File

@@ -1,17 +1,37 @@
## basalt.removeFrame
Removes the base frame by it's id. This only works for base-frames.
# Basalt
#### Parameters:
1. `string` id
## removeFrame
Removes the base frame by it's id. **This only works for base-frames.**
### Parameters
1. `string` id - ID of the base-frame.
### Usage
* Removes the previously created frame with id "secondBaseFrame"
The frame id is gotten from a frame variable's `:getName()`
#### Usage:
* Removes the previously created frame with id "myFirstFrame"
```lua
local main = basalt.createFrame("firstBaseFrame")
local main2 = basalt.createFrame("secondBaseFrame")
main:addButton()
:setText("Remove")
:onClick(function()
basalt.removeFrame(main2:getName()) -- you can use main2:getName() to find out the id or just use "secondBaseFrame"
basalt.removeFrame(main2:getName())
end)
```
```
* Removes the previously created frame with id "secondBaseFrame", without frame stored in variable
The frame id is the frame's name
```lua
local main = basalt.createFrame("firstBaseFrame")
local main2 = basalt.createFrame("secondBaseFrame")
main:addButton()
:setText("Remove")
:onClick(function()
basalt.removeFrame("secondBaseFrame")
end)
```

View File

@@ -1,14 +1,22 @@
## basalt.schedule
Schedules a function which gets called in a coroutine. After the coroutine is finished it will get destroyed immediatly. It's something like threads, but with some limits.
# Basalt
## schedule
Schedules a function which gets called in a coroutine. After the coroutine is finished it will get destroyed immediatly. It's something like threads, but with some limits.
**A guide can be found [here](/tips/logic).**
### Parameters
#### Parameters:
1. `function` a function which should get executed
#### Returns:
### Returns
1. `function` it returns the function which you have to execute in order to start the coroutine
#### Usage:
### Usage
* Creates a schedule which switches the color between red and gray
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setText("Click me")
@@ -25,4 +33,4 @@ aButton:onClick(basalt.schedule(function(self)
os.sleep(0.1)
self:setBackground(colors.gray)
end))
```
```

View File

@@ -0,0 +1,13 @@
# Basalt
## setActiveFrame
Sets what should be the active baseframe.
### Parameters
1. `frame` frame - The frame that should be the active base-frame.
### Usage
TODO

View File

@@ -0,0 +1,18 @@
# Basalt
## setMouseDragThrottle
Changes the drag throttle of all drag events. Default value is 50ms - which is 0.05s.
Instead of sending all mouse_drag events to the :onDrag handlers basalt sends every 0.05s (while dragging) the most recent drag event to all
drag handlers. If you need all drag events - just change the value to 0.
### Parameters
1. `number` A number in miliseconds.
### Usage
```lua
local basalt = require("basalt")
basalt.setMouseDragThrottle(0)
```

View File

@@ -0,0 +1,20 @@
# Basalt
## setMouseMoveThrottle
This feature is only available for [CraftOS-PC](https://www.craftos-pc.cc).
CraftOS-PC has a builtin mouse_move event, which is disabled by default. By using this method it will also enable the event for you. Remember - basalt does not disable the event after closing the program, which means the event stays active. If you want to disable the event please use config.set("mouse_move_throttle", -1) in your lua prompt or your program.
Sidenote: a very low amount can make the program laggy - because it litterally spams the mouse_move event. So use it carefully.
### Parameters
1. `number` A number in miliseconds.
### Usage
```lua
local basalt = require("basalt")
basalt.setMouseMoveThrottle(50)
```

View File

@@ -1,15 +1,21 @@
## basalt.setTheme
Sets the base theme of the project! Make sure to cover all existing objects, otherwise it will result in errors. A good example is [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua)
# Basalt
## setTheme
Sets the base theme of the project! Make sure to cover all existing objects, otherwise it will result in errors. A good example is [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua). The theme can also be gotten with [`basalt.getTheme()`](objects/Basalt/getTheme)
### Parameters
#### Parameters:
1. `table` theme layout look into [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for a example
#### Usage:
### Usage
* Sets the default theme of basalt.
```lua
basalt.setTheme({
ButtonBG = colors.yellow,
ButtonText = colors.red,
...,
})
```
```

View File

@@ -1,17 +1,25 @@
## basalt.setVariable
# Basalt
## setVariable
This stores a variable which you're able to access via xml. You are also able to add a function, which then gets called by object events created in XML.
#### Parameters:
1. `string` a key name
1. `any` any variable
### Parameters
1. `string` a key name
2. `any` any variable
### Usage
#### Usage:
* Adds a function to basalt.
```lua
basalt.setVariable("clickMe", function()
basalt.debug("I got clicked")
end)
```
```xml
<button onClick="clickMe" text="Click me" />
```
```

View File

@@ -1,15 +1,21 @@
## basalt.stopUpdate or basalt.stop
Stops the automatic draw and event handler which got started by basalt.autoUpdate()
# Basalt
## stopUpdate / stop
Stops the automatic draw and event handler which got started by `basalt.autoUpdate()`.
`basalt.autoUpdate(false)` also does the same.
### Usage
#### Usage:
* When the quit button is clicked, the button stops basalt's event listeners and draw handlers
```lua
local main = basalt.createFrame()
local aButton = main:addButton()
main:addButton()
:setPosition(2,2)
:setText("Stop Basalt!")
:onClick(function()
basalt.stopUpdate()
end)
basalt.autoUpdate()
```
```

View File

@@ -1,18 +1,24 @@
## basalt.update
# Basalt
## update
Calls the draw and event handler once - this gives more flexibility about which events basalt should process. For example you could filter the terminate event.
Which means you have to pass the events into basalt.update.
#### Parameters:
1. `string` The event to be received
### Parameters
1. `string` The event to be received
2. `...` Additional event variables to capture
#### Usage:
### Usage
* Creates and starts a custom update cycle
```lua
local mainFrame = basalt.createFrame()
local aButton = mainFrame:addButton():setPosition(2,2)
mainFrame:addButton():setPosition(2,2)
while true do
local ev = table.pack(os.pullEventRaw())
basalt.update(table.unpack(ev))
end
```
```

View File

@@ -28,6 +28,7 @@ some special functionality to create very advanced programs.
|[setScrollAmount](objects/Frame/setScrollAmount.md)|Sets how far the user is allowed to scroll
This is how you would implement frames via xml:
```xml
<frame>
<frame width="parent.w * 0.5" bg="red">
@@ -37,4 +38,297 @@ This is how you would implement frames via xml:
<textfield bg="green" x="2" width="parent.w-2" />
</frame>
</frame>
```
```
## Examples
Here are some examples on how you can use frames to create very advanced programs. Because of the screen size limitation of CC:Tweaked frames can become very useful in almost every scenario. You will find some examples here on how you could implement them.
### Menubar for switching frames
This is a example on how you can create a menubar which switches your frames (without animation).
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt") -- we need basalt here
local main = basalt.createFrame():setTheme({FrameBG = colors.lightGray, FrameFG = colors.black}) -- we change the default bg and fg color for frames
local sub = { -- here we create a table where we gonna add some frames
main:addFrame():setPosition(1, 2):setSize("parent.w", "parent.h - 1"), -- obviously the first one should be shown on program start
main:addFrame():setPosition(1, 2):setSize("parent.w", "parent.h - 1"):hide(),
main:addFrame():setPosition(1, 2):setSize("parent.w", "parent.h - 1"):hide(),
}
local function openSubFrame(id) -- we create a function which switches the frame for us
if(sub[id]~=nil)then
for k,v in pairs(sub)do
v:hide()
end
sub[id]:show()
end
end
local menubar = main:addMenubar():setScrollable() -- we create a menubar in our main frame.
:setSize("parent.w")
:onChange(function(self, val)
openSubFrame(self:getItemIndex()) -- here we open the sub frame based on the table index
end)
:addItem("Example 1")
:addItem("Example 2")
:addItem("Example 3")
-- Now we can change our sub frames, if you want to access a sub frame just use sub[subid], some examples:
sub[1]:addButton():setPosition(2, 2)
sub[2]:addLabel():setText("Hello World!"):setPosition(2, 2)
sub[3]:addLabel():setText("Now we're on example 3!"):setPosition(2, 2)
sub[3]:addButton():setText("No functionality"):setPosition(2, 4):setSize(18, 3)
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/frames-with-menubars.mp4" type="video/mp4">
</video>
### Sidebar with buttons to switch frames
Here we will find out how to create a sidebar (which are also just frames) - the sidebar should have buttons to opens the frames for us.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt") -- we need basalt here
local main = basalt.createFrame():setTheme({FrameBG = colors.lightGray, FrameFG = colors.black})
--[[
Here we create the sidebar, on focus it should change the position to parent.w - (self.w-1) which "opens the frame"
when the focus gets lost we simply change the position to "parent.w"
As you can see we add :setZIndex(25) - this makes sure the sidebar frame is always more important than our normal sub frames.
:setScrollable just makes the sidebar frame scrollable (in case you're adding more frames)
]]
local sidebar = main:addFrame():setBackground(colors.gray):setPosition("parent.w", 1):setSize(15, "parent.h"):setZIndex(25):setScrollable()
:onGetFocus(function(self)
self:setPosition("parent.w - (self.w-1)")
end)
:onLoseFocus(function(self)
self:setPosition("parent.w")
end)
-- Once again we add 3 frames, the first one should be immediatly visible
local sub = {
main:addFrame():setPosition(1, 1):setSize("parent.w", "parent.h"),
main:addFrame():setPosition(1, 1):setSize("parent.w", "parent.h"):hide(),
main:addFrame():setPosition(1, 1):setSize("parent.w", "parent.h"):hide(),
}
--This part of the code adds buttons based on the sub table.
local y = 2
for k,v in pairs(sub)do
sidebar:addButton():setText("Example "..k) -- creating the button and adding a name k is just the index
:setBackground(colors.black)
:setForeground(colors.lightGray)
:setSize("parent.w - 2", 3)
:setPosition(2, y)
:onClick(function() -- here we create a on click event which hides ALL sub frames and then shows the one which is linked to the button
for a, b in pairs(sub)do
b:hide()
v:show()
end
end)
y = y + 4
end
sub[1]:addButton():setPosition(2, 2)
sub[2]:addLabel():setText("Hello World!"):setPosition(2, 2)
sub[3]:addLabel():setText("Now we're on example 3!"):setPosition(2, 2)
sub[3]:addButton():setText("No functionality"):setPosition(2, 4):setSize(18, 3)
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/frames-with-sidebar.mp4" type="video/mp4">
</video>
### Movable frames with a program object
In this example you will see how you can add movable frames with a program object in it. It also shows you how you dynamically add new frames.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt")
local main = basalt.createFrame():setTheme({FrameBG = colors.lightGray, FrameFG = colors.black})
local id = 1
local processes = {}
local function openProgram(path, title, x, y, w, h)
local pId = id
id = id + 1
local f = main:addFrame()
:setMovable()
:setSize(w or 30, h or 12)
:setPosition(x or math.random(2, 12), y or math.random(2, 8))
f:addLabel()
:setSize("parent.w", 1)
:setBackground(colors.black)
:setForeground(colors.lightGray)
:setText(title or "New Program")
f:addProgram()
:setSize("parent.w", "parent.h - 1")
:setPosition(1, 2)
:execute(path or "rom/programs/shell.lua")
f:addButton()
:setSize(1, 1)
:setText("X")
:setBackground(colors.black)
:setForeground(colors.red)
:setPosition("parent.w", 1)
:onClick(function()
f:remove()
processes[pId] = nil
end)
processes[pId] = f
return f
end
openProgram("rom/programs/fun/worm.lua")
main:addButton():setPosition("parent.w - 16", 2):setText("Open"):onClick(function()
openProgram()
end)
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/dynamic-frames.mp4" type="video/mp4">
</video>
### Resizable frames
If you want to make your frames resizeable, there is no way offered by basalt - so you would have to do it yourself. However such a implementation is very simple as you can see here.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt")
local main = basalt.createFrame():setTheme({FrameBG = colors.black, FrameFG = colors.lightGray})
local sub = main:addFrame():setSize(25, 12):setPosition(3, 3)
local function makeResizeable(frame, minW, minH, maxW, maxH)
minW = minW or 4
minH = minH or 4
maxW = maxW or 99
maxH = maxH or 99
local btn = frame:addButton()
:setPosition("parent.w", "parent.h")
:setSize(1, 1)
:setText("/")
:setForeground(colors.blue)
:setBackground(colors.black)
:onDrag(function(self, event, btn, xOffset, yOffset)
local w, h = frame:getSize()
local wOff, hOff = w, h
if(w+xOffset-1>=minW)and(w+xOffset-1<=maxW)then
wOff = w+xOffset-1
end
if(h+yOffset-1>=minH)and(h+yOffset-1<=maxH)then
hOff = h+yOffset-1
end
frame:setSize(wOff, hOff)
end)
end
makeResizeable(sub, 8, 4)
sub:addLabel():setText("Hello World")
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/resizable-frames.mp4" type="video/mp4">
</video>
### Scrollable frames
Another important feature of frames is the possibility to make them scrollable. Basalt only provides vertical scrolling for frames. If you want to make horizontal scrolling possible, you need to do it yourself. Also, if you're using :setScrollable() the amount to scroll is based on the object's y-position + height - you can change this by using :setScrollAmount(amount). Only count's for the basalt implementation of scrollable frames.
<details>
<summary>Click here to show code</summary>
```lua
local basalt = require("basalt")
local main = basalt.createFrame():setTheme({FrameBG = colors.black, FrameFG = colors.lightGray})
-- Vertical scrolling is pretty simple, as you can tell:
local sub1 = main:addFrame():setScrollable():setSize(20, 15):setPosition(2, 2)
sub1:addLabel():setPosition(3, 2):setText("Scrollable")
sub1:addLabel():setPosition(3, 12):setText("Inside")
sub1:addLabel():setPosition(3, 20):setText("Outside")
-- Here we create a custom scroll event as you can see we dont add a :setScrollable() method to our frame, instead we add a custom scroll event
local objects = {}
local sub2 = main:addFrame():setPosition(23, 2):setSize(25, 5):onScroll(function(self, event, dir)
local maxScroll = 0
for k,v in pairs(objects)do -- here we iterate trough every object and get their x position + width this way we can find out what's the maximum allowed value to scroll
local x = v:getX()
local w = v:getWidth()
maxScroll = x + w > maxScroll and x + w or maxScroll -- if you don't understand this line, http://lua-users.org/wiki/TernaryOperator
end
local xOffset = self:getOffset()
if(xOffset+dir>=0 and xOffset+dir<=maxScroll-self:getWidth())then
self:setOffset(xOffset+dir, 0)
end
end)
-- Because we need to iterate the objects, we add them into a table.
table.insert(objects, sub2:addButton():setPosition(2, 2):setText("Scrollable"))
table.insert(objects, sub2:addButton():setPosition(16, 2):setText("Inside"))
table.insert(objects, sub2:addButton():setPosition(30, 2):setText("Outside"))
basalt.autoUpdate()
```
</details>
<br>
<video width="600" controls autoplay loop muted>
<source src="./_media/scrollable-frames.mp4" type="video/mp4">
</video>

View File

@@ -1,17 +1,22 @@
## setTheme
Sets the default theme of that frame children objects always try to get the theme of its parent frame, if it does not exist it goes to its parent parent frame, and so on until it reaches the basalt managers theme - which is sotred in theme.lua (Please checkout [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for how it could look like.
#### Parameters:
Sets the default theme, of that frame children objects always try to get the theme of its parent frame, if it does not exist it goes to its parent parent frame, and so on until it reaches the basalt manager's theme - which is stored in theme.lua (Please checkout [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for how it could look like.
#### Parameters:
1. `table` theme layout look into [theme](https://github.com/Pyroxenium/Basalt/blob/master/Basalt/theme.lua) for a example
#### Returns:
1. `frame` The frame being used
#### Usage:
* Creates a new base frame and adds a new theme which only changes the default color of buttons.
- Creates a new base frame and adds a new theme which only changes the default color of buttons.
```lua
local myFrame = basalt.createFrame():setTheme({
ButtonBG = colors.yellow,
ButtonText = colors.red,
})
```
```

View File

@@ -1,12 +1,18 @@
The image object is for adding more advanced backgrounds.
It also provides a :shrink() function, where you can shrink the images to smaller ones. This functionallity is fully provided by the blittle library created by Bomb Bloke. I did not ask for permission to add it into the framework. If the creator wants me to remove the blittle part, just text me on discord!
The image object is still not done. in the future i will provide more image formats.
The image object is for adding more advanced backgrounds to your interface. It supports the loading of .nfp and .bimg images.
[Object](objects/Object.md) methods also apply for images.
| | |
|---|---|
|[loadImage](objects/Image/loadImage.md)|Adds a new object
|[shrink](objects/Image/shrink.md)|Sets the top bar text and colors - deprecated
|[loadImage](objects/Image/loadImage.md)|Loads an image from the specified file path
|[setImage](objects/Image/setImage.md)|Set's a new image
|[usePalette](objects/Image/usePalette.md)|Changes the used palette to the image prefered palette
|[play](objects/Image/play.md)|Plays an animated image
|[selectFrame](objects/Image/selectFrame.md)|Selects a specific frame in an animated image
|[getMetadata](objects/Image/getMetadata.md)|Returns the metadata of the image
|[getImageSize](objects/Image/getImageSize.md)|Returns the width and height of the image
|[resizeImage](objects/Image/resizeImage.md)|Resizes the image to the specified dimensions
# About Bimg
Bimg is a custom image format that can be used in place of .nfp, it is a table which can store multiple frames and metadata. The frames can store text, background and foreground, which makes it possible to create any image you'd like. The image format is made by people from the Minecraft Computercraft Mods - Discord. Here's a Github page which explains how the Bimg format works: [bimg](https://github.com/SkyTheCodeMaster/bimg)

View File

@@ -0,0 +1,6 @@
## getImageSize
Returns the current image size
#### Returns:
1. `number` width
2. `number` height

View File

@@ -0,0 +1,9 @@
## getMetadata
Returns the metadata set in the image
#### Parameter:
1. `string` the metadata key (for example: title, description, author, creator, data, width, height,...)
#### Returns:
1. `any` metadata value

View File

@@ -1,18 +1,23 @@
## loadImage
loads a default .nfp file into the object.
This method is used to load an image file into the image object.
#### Parameters:
1. `string` the absolute file path
1. `path` the absolute file path
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default image and loads a test.nfp file
```lua
local mainFrame = basalt.createFrame()
local aImage = mainFrame:addImage():loadImage("test.nfp")
```
```xml
<image path="test.nfp" />
```
```

View File

@@ -0,0 +1,10 @@
## play
Plays a bimg animation. This can only work if the bimg has more than 1 frame.
#### Parameters:
1. `boolean` If the image animation should play
#### Returns:
1. `object` The object in use

View File

@@ -0,0 +1,19 @@
## resizeImage
This method is used to resize a bimg image. It takes two parameters: the new width, and the new height. It is important to note that resizing images can result in a loss of quality, as the original pixel data is being transformed and resampled to fit the new dimensions. This is especially noticeable when increasing the size of an image, as new pixels must be generated to fill in the gaps. As a result, it is generally recommended to use the original image at its full size whenever possible, rather than resizing it.
#### Parameters:
1. `number` the new width
2. `number` the new height
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a new image object, loads the image and changes it's size.
```lua
local mainFrame = basalt.createFrame()
local aImage = mainFrame:addImage():loadImage("test.bimg"):resizeImage(40, 20)
```

View File

@@ -0,0 +1,19 @@
## selectFrame
The selectFrame method allows you to change the current frame of an image object. It takes a single parameter, the index of the frame you want to display.
#### Parameters:
1. `number` the frame index
#### Returns:
1. `object` The object in use
#### Usage:
* Creates a default image and loads a test.nfp file
```lua
local mainFrame = basalt.createFrame()
local aImage = mainFrame:addImage():loadImage("test.bimg"):selectFrame(2)
```

View File

@@ -0,0 +1,23 @@
## setImage
Sets a new image
#### Parameter:
1. `table` A table in bimg or nfp format.
1. `string` The format in which the image should be loaded (nfp or bimg)
#### Usage:
* Creates a default image and loads a test.nfp file
```lua
local mainFrame = basalt.createFrame()
local bimg = {
[1] = {
{"Hello", "fffff", "33333"}
}
}
local aImage = mainFrame:addImage():setImage(bimg)
```

View File

@@ -0,0 +1,11 @@
## usePalette
Changes the palette colors of the image, if the bimg image has palette metadata.
#### Parameter:
1. `boolean` if the image should change the palette
#### Returns:
1. `object` The object in use

View File

@@ -1,6 +1,6 @@
This is the base class for all visual objects. It covers positioning, sizing, showing/hiding and much more.
By default a freshly created object is visible and automatically listens to all incoming events.
By default a freshly created object is visible and doesn't listens to any incoming events.
Its default position is always 1, 1 (based on it's parent frame). The default anchor is also topLeft.
| | |
@@ -10,6 +10,7 @@ Its default position is always 1, 1 (based on it's parent frame). The default an
|[isVisible](objects/Object/isVisible.md)|Returns if the object is currently visible
|[enable](objects/Object/enable.md)|Listens to incoming events
|[disable](objects/Object/disable.md)|Ignores all incoming events
|[remove](objects/Object/remove.md)|Removes the children object from it's parent object
|[setPosition](objects/Object/setPosition.md)|Changes the position (x,y)
|[getPosition](objects/Object/getPosition.md)|Returns the current position
|[setBackground](objects/Object/setBackground.md)|Changes the object's background
@@ -31,16 +32,42 @@ Its default position is always 1, 1 (based on it's parent frame). The default an
# Events
This is a list of all available events for all objects:
| | |
|---|---|
|[onClick](objects/Object/onClick.md)|Fires as soon as the object gets clicked
|[onClickUp](objects/Object/onClickUp.md)|Fires as soon as the mouse button gets released on the object
|[onScroll](objects/Object/onScroll.md)|Fires as soon as you scroll with the mousewheel
|[onRelease](objects/Object/onRelease.md)|Fires as soon as the mouse button gets released
|[onScroll](objects/Object/onScroll.md)|Fires as soon as you scroll with the mousewheel
|[onDrag](objects/Object/onDrag.md)|Fires as soon as the object is beeing dragged
|[onHover](objects/Object/onHover.md)|CraftOS-PC - fires when the mouse hovers over a object
|[onLeave](objects/Object/onLeave.md)|CraftOS-PC - fires when the mouse leaves a object
|[onKey](objects/Object/onKey.md)|Fires when the object is focused and a keyboard key has been clicked
|[onChar](objects/Object/onChar.md)|Fires when the object is focused and a character has been clicked
|[onKeyUp](objects/Object/onKeyUp.md)|Fires when the object is focused and a keyboard key has been released
|[onChange](objects/Object/onChange.md)|Fires when the object value has been changed
|[onResize](objects/Object/onResize.md)|Fires when the object got resized
|[onReposition](objects/Object/onReposition.md)|Fires when the object has been repositioned
|[onGetFocus](objects/Object/onGetFocus.md)|Fires when the object is focused
|[onLoseFocus](objects/Object/onLoseFocus.md)|Fires when the object lost it's focus
|[onLoseFocus](objects/Object/onLoseFocus.md)|Fires when the object lost it's focus
|[onEvent](objects/Object/onEvent.md)|Fires on any other event
Sidenote: When you use return false this will skip the object's event handler. Here is a example for that.
This code would make it impossible to write a into the input:
```lua
local basalt = require("basalt")
local main = basalt.createFrame()
local input = main:addInput()
:setPosition(3,3)
function checkInput(self, event, char)
if(char=="a")then
return false
end
end
main:onChar(checkInput)
```

View File

@@ -1,4 +1,7 @@
# Object
## disable
Disables the object's event listeners
This will disable the object. Which means it doesn't listen to any events anymore.
This will disable the object. Which means it doesn't listen to any events anymore.

View File

@@ -1,4 +1,7 @@
# Object
## enable
Enables the object's event listeners
If the object's is disabled, it will stop listening to incoming events, this will reenable it.
If the object's is disabled, it will stop listening to incoming events, this will reenable it.

View File

@@ -1,16 +1,24 @@
# Object
## getAbsolutePosition
Converts the relative coordinates into absolute coordinates
#### Parameters:
### Parameters
1. `number|nil` x
2. `number|nil` y
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
### Usage
* Creates a frame and a button and prints the button's absolute position to the debug console
```lua
local mainFrame = basalt.createFrame():setPosition(3,3)
local aButton = mainFrame:addButton():setSize(8,1):setPosition(4,2)
basalt.debug(aButton:getAbsolutePosition()) -- returns 7,5 (frame coords + own coords) instead of 4,2
```
```

View File

@@ -1,16 +1,23 @@
# Object
## getAnchorPosition
Converts the x and y coordinates into the anchor coordinates of the object
#### Parameters:
### Parameters
1. `number|nil` x
2. `number|nil` y, if nothing it uses the object's x, y
#### Returns:
#### Returns
1. `number` x
2. `number` y
#### Usage:
#### Usage
* Prints the anchor position to the debug console
```lua
local mainFrame = basalt.createFrame():setSize(15,15)
local aButton = mainFrame:addButton()
@@ -18,4 +25,4 @@ local aButton = mainFrame:addButton()
:setSize(8,1)
:setPosition(1,1)
basalt.debug(aButton:getAnchorPosition()) -- returns 7,14 (framesize - own size) instead of 1,1
```
```

View File

@@ -1,5 +1,9 @@
# Object
## getBackground
Returns the current background color
#### Returns:
### Returns
1. `number` color

View File

@@ -1,5 +1,9 @@
# Object
## getForeground
Returns the current foreground color
#### Returns:
### Returns
1. `number` color

View File

@@ -1,11 +1,17 @@
# Object
## getName
Returns the given name of the object
#### Returns:
### Returns
1. `string` name
#### Usage:
#### Usage
* Prints name of object to debug window
```lua
local main = basalt.createFrame()
basalt.debug(main:getName()) -- returns the uuid
@@ -14,4 +20,4 @@ basalt.debug(main:getName()) -- returns the uuid
```lua
local main = basalt.createFrame("myFirstMainFrame")
basalt.debug(main:getName()) -- returns myFirstMainFrame
```
```

View File

@@ -1,6 +1,10 @@
# Object
## getPosition
Returns the object's position
#### Returns:
### Returns
1. `number` x
2. `number` y

View File

@@ -1,6 +1,10 @@
# Object
## getSize
Returns the object's size
#### Returns:
### Returns
1. `number` w
2. `number` h

View File

@@ -1,12 +1,19 @@
# Object
## getValue
Returns the currently saved value
#### Returns:
### Returns
1. `any` Object's value
#### Usage:
### Usage
* Prints the value of the checkbox to the debug console
```lua
local mainFrame = basalt.createFrame()
local aCheckbox = mainFrame:addCheckbox():setValue(true)
basalt.debug(aCheckbox:getValue()) -- returns true
```
```

View File

@@ -1,15 +1,22 @@
# Object
## hide
Hides the object
#### Returns:
### Returns
1. `object` The object in use
#### Usage:
#### Usage
* Hides a frame
```lua
local mainFrame = basalt.createFrame()
local button = mainFrame:addButton():setText("Close"):onClick(function() mainFrame:hide() end)
```
```xml
<button visible="false" />
```
```

Some files were not shown because too many files have changed in this diff Show More