From 051abd04e4527095ef15412939450fbe504daebe Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 26 Oct 2021 19:33:40 +0800 Subject: +texture & imagedata --- Data/Configs/Settings.json | 3 + .../Libraries/GameLab/Engine/Math/Vector2.lua | 5 +- .../Libraries/GameLab/Engine/Math/Vector3.lua | 6 +- .../Libraries/GameLab/Engine/Rendering/Image.lua | 20 + Data/DefaultContent/Libraries/lua-csv/.gitignore | 2 - Data/DefaultContent/Libraries/lua-csv/AUTHORS | 2 - Data/DefaultContent/Libraries/lua-csv/LICENSE | 22 - Data/DefaultContent/Libraries/lua-csv/README.md | 93 ---- .../DefaultContent/Libraries/lua-csv/lua/config.ld | 4 - Data/DefaultContent/Libraries/lua-csv/lua/csv.lua | 557 --------------------- Data/DefaultContent/Libraries/lua-csv/lua/test.lua | 102 ---- Data/DefaultContent/Libraries/lua-csv/makefile | 14 - .../Libraries/lua-csv/rockspecs/csv-1-1.rockspec | 24 - .../Libraries/lua-csv/rockspecs/csv-scm-1.rockspec | 23 - .../Libraries/lua-csv/test-data/BOM.csv | 3 - .../Libraries/lua-csv/test-data/bars.txt | 7 - .../Libraries/lua-csv/test-data/blank-line.csv | 2 - .../lua-csv/test-data/embedded-newlines.csv | 8 - .../lua-csv/test-data/embedded-quotes.csv | 2 - .../Libraries/lua-csv/test-data/header.csv | 3 - Data/DefaultContent/Resources/Images/white.png | Bin 0 -> 219 bytes Data/Libraries/GameLab/Editor/init.lua | 6 + Data/Libraries/lua-csv/.gitignore | 2 + Data/Libraries/lua-csv/AUTHORS | 2 + Data/Libraries/lua-csv/LICENSE | 22 + Data/Libraries/lua-csv/README.md | 93 ++++ Data/Libraries/lua-csv/lua/config.ld | 4 + Data/Libraries/lua-csv/lua/csv.lua | 557 +++++++++++++++++++++ Data/Libraries/lua-csv/lua/test.lua | 102 ++++ Data/Libraries/lua-csv/makefile | 14 + Data/Libraries/lua-csv/rockspecs/csv-1-1.rockspec | 24 + .../Libraries/lua-csv/rockspecs/csv-scm-1.rockspec | 23 + Data/Libraries/lua-csv/test-data/BOM.csv | 3 + Data/Libraries/lua-csv/test-data/bars.txt | 7 + Data/Libraries/lua-csv/test-data/blank-line.csv | 2 + .../lua-csv/test-data/embedded-newlines.csv | 8 + .../lua-csv/test-data/embedded-quotes.csv | 2 + Data/Libraries/lua-csv/test-data/header.csv | 3 + Data/Resources/Gizmos/Gizmos.xlsx | Bin 6184 -> 0 bytes Data/Resources/Icons/buttons/add.png | Bin 0 -> 314 bytes Data/Resources/Icons/buttons/alpha.png | Bin 0 -> 2898 bytes Data/Resources/Icons/buttons/checker.png | Bin 0 -> 2837 bytes Data/Resources/Icons/buttons/cog.png | Bin 0 -> 3217 bytes Data/Resources/Icons/buttons/del.png | Bin 0 -> 129 bytes Data/Resources/Icons/buttons/del2.png | Bin 0 -> 2903 bytes Data/Resources/Icons/buttons/del3.png | Bin 0 -> 3076 bytes Data/Resources/Icons/buttons/delete.png | Bin 0 -> 2927 bytes Data/Resources/Icons/buttons/disable.png | Bin 0 -> 2983 bytes Data/Resources/Icons/buttons/down.png | Bin 0 -> 2998 bytes Data/Resources/Icons/buttons/forward.png | Bin 0 -> 2926 bytes Data/Resources/Icons/buttons/invisible.png | Bin 0 -> 3321 bytes Data/Resources/Icons/buttons/lock.png | Bin 0 -> 2952 bytes Data/Resources/Icons/buttons/open.png | Bin 0 -> 2978 bytes Data/Resources/Icons/buttons/pause.png | Bin 0 -> 2941 bytes Data/Resources/Icons/buttons/pen.png | Bin 0 -> 3126 bytes Data/Resources/Icons/buttons/play.png | Bin 0 -> 3026 bytes Data/Resources/Icons/buttons/play2.png | Bin 0 -> 3018 bytes Data/Resources/Icons/buttons/pop_disabled.png | Bin 0 -> 2942 bytes Data/Resources/Icons/buttons/pop_hover.png | Bin 0 -> 2893 bytes Data/Resources/Icons/buttons/pop_normal.png | Bin 0 -> 2895 bytes Data/Resources/Icons/buttons/pop_selected.png | Bin 0 -> 2901 bytes Data/Resources/Icons/buttons/prefab_apply.png | Bin 0 -> 3053 bytes Data/Resources/Icons/buttons/prefab_revert.png | Bin 0 -> 3070 bytes Data/Resources/Icons/buttons/rgb.png | Bin 0 -> 2954 bytes Data/Resources/Icons/buttons/search.png | Bin 0 -> 2947 bytes Data/Resources/Icons/buttons/smalladd.png | Bin 0 -> 2947 bytes Data/Resources/Icons/buttons/smalldel.png | Bin 0 -> 2967 bytes Data/Resources/Icons/buttons/smalldisable.png | Bin 0 -> 3173 bytes Data/Resources/Icons/buttons/smalldisableempty.png | Bin 0 -> 2970 bytes Data/Resources/Icons/buttons/smalllock.png | Bin 0 -> 3012 bytes Data/Resources/Icons/buttons/star.png | Bin 0 -> 3246 bytes Data/Resources/Icons/buttons/stopplay.png | Bin 0 -> 2918 bytes Data/Resources/Icons/buttons/up.png | Bin 0 -> 2990 bytes Data/Resources/Images/UI.csv | 2 - Data/Resources/Images/UI.xlsx | Bin 6625 -> 0 bytes Data/Resources/Images/brickwall.jpg | Bin 0 -> 198744 bytes Data/Resources/Metatable/Excel/Extract_All.cmd | 3 +- Data/Resources/Metatable/Excel/Extract_Shaders.cmd | 1 + Data/Resources/Metatable/Excel/Icons.xlsx | Bin 9170 -> 12385 bytes Data/Resources/Metatable/Excel/Shaders.xlsx | Bin 0 -> 8891 bytes Data/Resources/Metatable/Icons.csv | 15 +- Data/Resources/Metatable/Shaders.csv | 2 + Data/Scripts/EditorApplication.lua | 6 + Data/Scripts/EditorGUI/EditorImages.lua | 25 +- Data/boot.lua | 8 +- Projects/VisualStudio/Editor/Editor.vcxproj | 2 + .../VisualStudio/Editor/Editor.vcxproj.filters | 6 + Runtime/Debug/Log.cpp | 8 +- Runtime/FileSystem/FileJobs.h | 3 +- Runtime/Graphics/Device.h | 12 +- Runtime/Graphics/ImageData.h | 49 +- Runtime/Graphics/RenderTexture.h | 4 +- Runtime/Graphics/Texture.cpp | 69 +++ Runtime/Graphics/Texture.h | 103 ++-- Runtime/Lua/LuaHelper.cpp | 5 + Runtime/Lua/LuaHelper.h | 7 +- Runtime/Scripting/Rendering/ImageData.bind.cpp | 38 ++ Runtime/Scripting/Rendering/Rendering.bind.cpp | 32 ++ Runtime/Scripting/Rendering/Texture.bind.cpp | 143 ++++++ 99 files changed, 1375 insertions(+), 944 deletions(-) create mode 100644 Data/DefaultContent/Libraries/GameLab/Engine/Rendering/Image.lua delete mode 100644 Data/DefaultContent/Libraries/lua-csv/.gitignore delete mode 100644 Data/DefaultContent/Libraries/lua-csv/AUTHORS delete mode 100644 Data/DefaultContent/Libraries/lua-csv/LICENSE delete mode 100644 Data/DefaultContent/Libraries/lua-csv/README.md delete mode 100644 Data/DefaultContent/Libraries/lua-csv/lua/config.ld delete mode 100644 Data/DefaultContent/Libraries/lua-csv/lua/csv.lua delete mode 100644 Data/DefaultContent/Libraries/lua-csv/lua/test.lua delete mode 100644 Data/DefaultContent/Libraries/lua-csv/makefile delete mode 100644 Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-1-1.rockspec delete mode 100644 Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec delete mode 100644 Data/DefaultContent/Libraries/lua-csv/test-data/BOM.csv delete mode 100644 Data/DefaultContent/Libraries/lua-csv/test-data/bars.txt delete mode 100644 Data/DefaultContent/Libraries/lua-csv/test-data/blank-line.csv delete mode 100644 Data/DefaultContent/Libraries/lua-csv/test-data/embedded-newlines.csv delete mode 100644 Data/DefaultContent/Libraries/lua-csv/test-data/embedded-quotes.csv delete mode 100644 Data/DefaultContent/Libraries/lua-csv/test-data/header.csv create mode 100644 Data/DefaultContent/Resources/Images/white.png create mode 100644 Data/Libraries/lua-csv/.gitignore create mode 100644 Data/Libraries/lua-csv/AUTHORS create mode 100644 Data/Libraries/lua-csv/LICENSE create mode 100644 Data/Libraries/lua-csv/README.md create mode 100644 Data/Libraries/lua-csv/lua/config.ld create mode 100644 Data/Libraries/lua-csv/lua/csv.lua create mode 100644 Data/Libraries/lua-csv/lua/test.lua create mode 100644 Data/Libraries/lua-csv/makefile create mode 100644 Data/Libraries/lua-csv/rockspecs/csv-1-1.rockspec create mode 100644 Data/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec create mode 100644 Data/Libraries/lua-csv/test-data/BOM.csv create mode 100644 Data/Libraries/lua-csv/test-data/bars.txt create mode 100644 Data/Libraries/lua-csv/test-data/blank-line.csv create mode 100644 Data/Libraries/lua-csv/test-data/embedded-newlines.csv create mode 100644 Data/Libraries/lua-csv/test-data/embedded-quotes.csv create mode 100644 Data/Libraries/lua-csv/test-data/header.csv delete mode 100644 Data/Resources/Gizmos/Gizmos.xlsx create mode 100644 Data/Resources/Icons/buttons/add.png create mode 100644 Data/Resources/Icons/buttons/alpha.png create mode 100644 Data/Resources/Icons/buttons/checker.png create mode 100644 Data/Resources/Icons/buttons/cog.png create mode 100644 Data/Resources/Icons/buttons/del.png create mode 100644 Data/Resources/Icons/buttons/del2.png create mode 100644 Data/Resources/Icons/buttons/del3.png create mode 100644 Data/Resources/Icons/buttons/delete.png create mode 100644 Data/Resources/Icons/buttons/disable.png create mode 100644 Data/Resources/Icons/buttons/down.png create mode 100644 Data/Resources/Icons/buttons/forward.png create mode 100644 Data/Resources/Icons/buttons/invisible.png create mode 100644 Data/Resources/Icons/buttons/lock.png create mode 100644 Data/Resources/Icons/buttons/open.png create mode 100644 Data/Resources/Icons/buttons/pause.png create mode 100644 Data/Resources/Icons/buttons/pen.png create mode 100644 Data/Resources/Icons/buttons/play.png create mode 100644 Data/Resources/Icons/buttons/play2.png create mode 100644 Data/Resources/Icons/buttons/pop_disabled.png create mode 100644 Data/Resources/Icons/buttons/pop_hover.png create mode 100644 Data/Resources/Icons/buttons/pop_normal.png create mode 100644 Data/Resources/Icons/buttons/pop_selected.png create mode 100644 Data/Resources/Icons/buttons/prefab_apply.png create mode 100644 Data/Resources/Icons/buttons/prefab_revert.png create mode 100644 Data/Resources/Icons/buttons/rgb.png create mode 100644 Data/Resources/Icons/buttons/search.png create mode 100644 Data/Resources/Icons/buttons/smalladd.png create mode 100644 Data/Resources/Icons/buttons/smalldel.png create mode 100644 Data/Resources/Icons/buttons/smalldisable.png create mode 100644 Data/Resources/Icons/buttons/smalldisableempty.png create mode 100644 Data/Resources/Icons/buttons/smalllock.png create mode 100644 Data/Resources/Icons/buttons/star.png create mode 100644 Data/Resources/Icons/buttons/stopplay.png create mode 100644 Data/Resources/Icons/buttons/up.png delete mode 100644 Data/Resources/Images/UI.csv delete mode 100644 Data/Resources/Images/UI.xlsx create mode 100644 Data/Resources/Images/brickwall.jpg create mode 100644 Data/Resources/Metatable/Excel/Extract_Shaders.cmd create mode 100644 Data/Resources/Metatable/Excel/Shaders.xlsx create mode 100644 Data/Resources/Metatable/Shaders.csv create mode 100644 Runtime/Scripting/Rendering/ImageData.bind.cpp create mode 100644 Runtime/Scripting/Rendering/Texture.bind.cpp diff --git a/Data/Configs/Settings.json b/Data/Configs/Settings.json index e69de29..cb92a2e 100644 --- a/Data/Configs/Settings.json +++ b/Data/Configs/Settings.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector2.lua b/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector2.lua index 5697797..822537f 100644 --- a/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector2.lua +++ b/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector2.lua @@ -1,5 +1,8 @@ local Vector2 = GameLab.Class("GameLab.Engine.Math.Vector2") - +Vector2.Ctor = function(self, x, y) + self.x = x or 0 + self.y = y or 0 +end return Vector2 \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector3.lua b/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector3.lua index caa28a4..e383bf0 100644 --- a/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector3.lua +++ b/Data/DefaultContent/Libraries/GameLab/Engine/Math/Vector3.lua @@ -1,5 +1,9 @@ local Vector3 = GameLab.Class("GameLab.Engine.Math.Vector3") - +Vector3.Ctor = function(self, x, y, z) + self.x = x or 0 + self.y = y or 0 + self.z = z or 0 +end return Vector3 \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/GameLab/Engine/Rendering/Image.lua b/Data/DefaultContent/Libraries/GameLab/Engine/Rendering/Image.lua new file mode 100644 index 0000000..b209425 --- /dev/null +++ b/Data/DefaultContent/Libraries/GameLab/Engine/Rendering/Image.lua @@ -0,0 +1,20 @@ +-- Image在texture基础上增加了一些元数据 +local Image = GameLab.Class("GameLab.Engine.Rendering.Image") + +Image.Ctor = function(self, texture) + self.texture = texture -- "atlas" + self.rect = {0, 0, 1, 1} -- 这个image在texture中的位置 + self.isSlicing = false + self.slicing = {0, 0, 0, 0} +end + +Image.GetWidth = function(self) +end + +Image.GetHeight = function(self) +end + +Image.GetSize = function(self) +end + +return Image \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/lua-csv/.gitignore b/Data/DefaultContent/Libraries/lua-csv/.gitignore deleted file mode 100644 index 131f9b6..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.DS_Store -lua/docs \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/lua-csv/AUTHORS b/Data/DefaultContent/Libraries/lua-csv/AUTHORS deleted file mode 100644 index 84961bd..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Leyland, Geoff -Martin, Kevin diff --git a/Data/DefaultContent/Libraries/lua-csv/LICENSE b/Data/DefaultContent/Libraries/lua-csv/LICENSE deleted file mode 100644 index d8472a0..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2013-2014 Incremental IP Limited -Copyright (c) 2014 Kevin Martin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - diff --git a/Data/DefaultContent/Libraries/lua-csv/README.md b/Data/DefaultContent/Libraries/lua-csv/README.md deleted file mode 100644 index d10314a..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Lua-CSV - delimited file reading - -## 1. What? - -Lua-CSV is a Lua module for reading delimited text files (popularly CSV and -tab-separated files, but you can specify the separator). - -Lua-CSV tries to auto-detect whether a file is delimited with commas or tabs, -copes with non-native newlines, survives newlines and quotes inside quoted -fields and offers an iterator interface so it can handle large files. - - -## 2. How? - - local csv = require("csv") - local f = csv.open("file.csv") - for fields in f:lines() do - for i, v in ipairs(fields) do print(i, v) end - end - -`csv.open` takes a second argument `parameters`, a table of parameters -controlling how the file is read: - -+ `separator` sets the separator. It'll probably guess the separator - correctly if it's a comma or a tab (unless, say, the first field in a - tab-delimited file contains a comma), but if you want something else you'll - have to set this. It could be more than one character, but it's used as - part of a set: `"["..sep.."\n\r]"` - -+ Set `header` to true if the file contains a header and each set of fields - will be keyed by the names in the header rather than by integer index. - -+ `columns` provides a mechanism for column remapping. - Suppose you have a csv file as follows: - - Word,Number - ONE,10 - - And columns is: - - + `{ word = true }` then the only field in the file would be - `{ word = "ONE" }` - + `{ first = { name = "word"} }` then it would be `{ first = "ONE" }` - + `{ word = { transform = string.lower }}` would give `{ word = "one" }` - + finally, - - { word = true - number = { transform = function(x) return tonumber(x) / 10 end }} - - would give `{ word = "ONE", number = 1 }` - - A column can have more than one name: - `{ first = { names = {"word", "worm"}}}` to help cope with badly specified - file formats and spelling mistakes. - -+ `buffer_size` controls the size of the blocks the file is read in. The - default is 1MB. It used to be 4096 bytes which is what `pagesize` says on - my system, but that seems kind of small. - -`csv.openstring` works exactly like `csv.open` except the first argument -is the contents of the csv file. In this case `buffer_size` is set to -the length of the string. - -## 3. Requirements - -Lua 5.1, 5.2 or LuaJIT. - - -## 4. Issues - -+ Some whitespace-delimited files might use more than one space between - fields, for example if the columns are "manually" aligned: - - street nr city - "Oneway Street" 1 Toontown - - It won't cope with this - you'll get lots of extra empty fields. - -## 5. Wishlist - -+ Tests would be nice. -+ So would better LDoc documentation. - - -## 6. Alternatives - -+ [Penlight](http://github.com/stevedonovan/penlight) contains delimited - file reading. It reads the whole file in one go. -+ The Lua Wiki contains two pages on CSV - [here](http://lua-users.org/wiki/LuaCsv) and - [here](http://lua-users.org/wiki/CsvUtils). -+ There's an example using [LPeg](http://www.inf.puc-rio.br/~roberto/lpeg/) - to parse CSV [here](http://www.inf.puc-rio.br/~roberto/lpeg/#CSV) diff --git a/Data/DefaultContent/Libraries/lua-csv/lua/config.ld b/Data/DefaultContent/Libraries/lua-csv/lua/config.ld deleted file mode 100644 index af51949..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/lua/config.ld +++ /dev/null @@ -1,4 +0,0 @@ -project = "Lua-CSV" -title = "Lua-CSV Source Documentation" -description = "Lua-CSV reads delimited text files" -format = "markdown" diff --git a/Data/DefaultContent/Libraries/lua-csv/lua/csv.lua b/Data/DefaultContent/Libraries/lua-csv/lua/csv.lua deleted file mode 100644 index 64196c0..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/lua/csv.lua +++ /dev/null @@ -1,557 +0,0 @@ ---- Read a comma or tab (or other delimiter) separated file. --- This version of a CSV reader differs from others I've seen in that it --- --- + handles embedded newlines in fields (if they're delimited with double --- quotes) --- + is line-ending agnostic --- + reads the file line-by-line, so it can potientially handle large --- files. --- --- Of course, for such a simple format, CSV is horribly complicated, so it --- likely gets something wrong. - --- (c) Copyright 2013-2014 Incremental IP Limited. --- (c) Copyright 2014 Kevin Martin --- Available under the MIT licence. See LICENSE for more information. - -local DEFAULT_BUFFER_BLOCK_SIZE = 1024 * 1024 - - ------------------------------------------------------------------------------- - -local function trim_space(s) - return s:match("^%s*(.-)%s*$") -end - - -local function fix_quotes(s) - -- the sub(..., -2) is to strip the trailing quote - return string.sub(s:gsub('""', '"'), 1, -2) -end - - ------------------------------------------------------------------------------- - -local column_map = {} -column_map.__index = column_map - - -local function normalise_string(s) - return (s:lower():gsub("[^%w%d]+", " "):gsub("^ *(.-) *$", "%1")) -end - - ---- Parse a list of columns. --- The main job here is normalising column names and dealing with columns --- for which we have more than one possible name in the header. -function column_map:new(columns) - local name_map = {} - for n, v in pairs(columns) do - local names - local t - if type(v) == "table" then - t = { transform = v.transform, default = v.default } - if v.name then - names = { normalise_string(v.name) } - elseif v.names then - names = v.names - for i, n in ipairs(names) do names[i] = normalise_string(n) end - end - else - if type(v) == "function" then - t = { transform = v } - else - t = {} - if type(v) == "string" then - names = { normalise_string(v) } - end - end - end - - if not names then - names = { (n:lower():gsub("[^%w%d]+", " ")) } - end - - t.name = n - for _, n in ipairs(names) do - name_map[n:lower()] = t - end - end - - return setmetatable({ name_map = name_map }, column_map) -end - - ---- Map "virtual" columns to file columns. --- Once we've read the header, work out which columns we're interested in and --- what to do with them. Mostly this is about checking we've got the columns --- we need and writing a nice complaint if we haven't. -function column_map:read_header(header) - local index_map = {} - - -- Match the columns in the file to the columns in the name map - local found = {} - local found_any - for i, word in ipairs(header) do - word = normalise_string(word) - local r = self.name_map[word] - if r then - index_map[i] = r - found[r.name] = true - found_any = true - end - end - - if not found_any then return end - - -- check we found all the columns we need - local not_found = {} - for name, r in pairs(self.name_map) do - if not found[r.name] then - local nf = not_found[r.name] - if nf then - nf[#nf+1] = name - else - not_found[r.name] = { name } - end - end - end - -- If any columns are missing, assemble an error message - if next(not_found) then - local problems = {} - for k, v in pairs(not_found) do - local missing - if #v == 1 then - missing = "'"..v[1].."'" - else - missing = v[1] - for i = 2, #v - 1 do - missing = missing..", '"..v[i].."'" - end - missing = missing.." or '"..v[#v].."'" - end - problems[#problems+1] = "Couldn't find a column named "..missing - end - error(table.concat(problems, "\n"), 0) - end - - self.index_map = index_map - return true -end - - -function column_map:transform(value, index) - local field = self.index_map[index] - if field then - if field.transform then - local ok - ok, value = pcall(field.transform, value) - if not ok then - error(("Error reading field '%s': %s"):format(field.name, value), 0) - end - end - return value or field.default, field.name - end -end - - ------------------------------------------------------------------------------- - -local file_buffer = {} -file_buffer.__index = file_buffer - -function file_buffer:new(file, buffer_block_size) - return setmetatable({ - file = file, - buffer_block_size = buffer_block_size or DEFAULT_BUFFER_BLOCK_SIZE, - buffer_start = 0, - buffer = "", - }, file_buffer) -end - - ---- Cut the front off the buffer if we've already read it -function file_buffer:truncate(p) - p = p - self.buffer_start - if p > self.buffer_block_size then - local remove = self.buffer_block_size * - math.floor((p-1) / self.buffer_block_size) - self.buffer = self.buffer:sub(remove + 1) - self.buffer_start = self.buffer_start + remove - end -end - - ---- Find something in the buffer, extending it if necessary -function file_buffer:find(pattern, init) - while true do - local first, last, capture = - self.buffer:find(pattern, init - self.buffer_start) - -- if we found nothing, or the last character is at the end of the - -- buffer (and the match could potentially be longer) then read some - -- more. - if not first or last == #self.buffer then - local s = self.file:read(self.buffer_block_size) - if not s then - if not first then - return - else - return first + self.buffer_start, last + self.buffer_start, capture - end - end - self.buffer = self.buffer..s - else - return first + self.buffer_start, last + self.buffer_start, capture - end - end -end - - ---- Extend the buffer so we can see more -function file_buffer:extend(offset) - local extra = offset - #self.buffer - self.buffer_start - if extra > 0 then - local size = self.buffer_block_size * - math.ceil(extra / self.buffer_block_size) - local s = self.file:read(size) - if not s then return end - self.buffer = self.buffer..s - end -end - - ---- Get a substring from the buffer, extending it if necessary -function file_buffer:sub(a, b) - self:extend(b) - b = b == -1 and b or b - self.buffer_start - return self.buffer:sub(a - self.buffer_start, b) -end - - ---- Close a file buffer -function file_buffer:close() - self.file:close() - self.file = nil -end - - ------------------------------------------------------------------------------- - -local separator_candidates = { ",", "\t", "|" } -local guess_separator_params = { record_limit = 8; } - - -local function try_separator(buffer, sep, f) - guess_separator_params.separator = sep - local min, max = math.huge, 0 - local lines, split_lines = 0, 0 - local iterator = coroutine.wrap(function() f(buffer, guess_separator_params) end) - for t in iterator do - min = math.min(min, #t) - max = math.max(max, #t) - split_lines = split_lines + (t[2] and 1 or 0) - lines = lines + 1 - end - if split_lines / lines > 0.75 then - return max - min - else - return math.huge - end -end - - ---- If the user hasn't specified a separator, try to work out what it is. -function guess_separator(buffer, f) - local best_separator, lowest_diff = "", math.huge - for _, s in ipairs(separator_candidates) do - local ok, diff = pcall(function() return try_separator(buffer, s, f) end) - if ok and diff < lowest_diff then - best_separator = s - lowest_diff = diff - end - end - - return best_separator -end - - -local unicode_BOMS = -{ - { - length = 2, - BOMS = - { - ["\254\255"] = true, -- UTF-16 big-endian - ["\255\254"] = true, -- UTF-16 little-endian - } - }, - { - length = 3, - BOMS = - { - ["\239\187\191"] = true, -- UTF-8 - } - } -} - - -local function find_unicode_BOM(sub) - for _, x in ipairs(unicode_BOMS) do - local code = sub(1, x.length) - if x.BOMS[code] then - return x.length - end - end - return 0 -end - - ---- Iterate through the records in a file --- Since records might be more than one line (if there's a newline in quotes) --- and line-endings might not be native, we read the file in chunks of --- we read the file in chunks using a file_buffer, rather than line-by-line --- using io.lines. -local function separated_values_iterator(buffer, parameters) - local field_start = 1 - - local advance - if buffer.truncate then - advance = function(n) - field_start = field_start + n - buffer:truncate(field_start) - end - else - advance = function(n) - field_start = field_start + n - end - end - - - local function field_sub(a, b) - b = b == -1 and b or b + field_start - 1 - return buffer:sub(a + field_start - 1, b) - end - - - local function field_find(pattern, init) - init = init or 1 - local f, l, c = buffer:find(pattern, init + field_start - 1) - if not f then return end - return f - field_start + 1, l - field_start + 1, c - end - - - -- Is there some kind of Unicode BOM here? - advance(find_unicode_BOM(field_sub)) - - - -- Start reading the file - local sep = "(["..(parameters.separator or - guess_separator(buffer, separated_values_iterator)).."\n\r])" - local line_start = 1 - local line = 1 - local field_count, fields, starts, nonblanks = 0, {}, {} - local header, header_read - local field_start_line, field_start_column - local record_count = 0 - - - local function problem(message) - error(("%s:%d:%d: %s"): - format(parameters.filename, field_start_line, field_start_column, - message), 0) - end - - - while true do - local field_end, sep_end, this_sep - local tidy - field_start_line = line - field_start_column = field_start - line_start + 1 - - -- If the field is quoted, go find the other quote - if field_sub(1, 1) == '"' then - advance(1) - local current_pos = 0 - repeat - local a, b, c = field_find('"("?)', current_pos + 1) - current_pos = b - until c ~= '"' - if not current_pos then problem("unmatched quote") end - tidy = fix_quotes - field_end, sep_end, this_sep = field_find(" *([^ ])", current_pos+1) - if this_sep and not this_sep:match(sep) then problem("unmatched quote") end - else - field_end, sep_end, this_sep = field_find(sep, 1) - tidy = trim_space - end - - -- Look for the separator or a newline or the end of the file - field_end = (field_end or 0) - 1 - - -- Read the field, then convert all the line endings to \n, and - -- count any embedded line endings - local value = field_sub(1, field_end) - value = value:gsub("\r\n", "\n"):gsub("\r", "\n") - for nl in value:gmatch("\n()") do - line = line + 1 - line_start = nl + field_start - end - - value = tidy(value) - if #value > 0 then nonblanks = true end - field_count = field_count + 1 - - -- Insert the value into the table for this "line" - local key - if parameters.column_map and header_read then - local ok - ok, value, key = pcall(parameters.column_map.transform, - parameters.column_map, value, field_count) - if not ok then problem(value) end - elseif header then - key = header[field_count] - else - key = field_count - end - if key then - fields[key] = value - starts[key] = { line=field_start_line, column=field_start_column } - end - - -- if we ended on a newline then yield the fields on this line. - if not this_sep or this_sep == "\r" or this_sep == "\n" then - if parameters.column_map and not header_read then - header_read = parameters.column_map:read_header(fields) - elseif parameters.header and not header_read then - if nonblanks or field_count > 1 then -- ignore blank lines - header = fields - header_read = true - end - else - if nonblanks or field_count > 1 then -- ignore blank lines - coroutine.yield(fields, starts) - record_count = record_count + 1 - if parameters.record_limit and - record_count >= parameters.record_limit then - break - end - end - end - field_count, fields, starts, nonblanks = 0, {}, {} - end - - -- If we *really* didn't find a separator then we're done. - if not sep_end then break end - - -- If we ended on a newline then count it. - if this_sep == "\r" or this_sep == "\n" then - if this_sep == "\r" and field_sub(sep_end+1, sep_end+1) == "\n" then - sep_end = sep_end + 1 - end - line = line + 1 - line_start = field_start + sep_end - end - - advance(sep_end) - end -end - - ------------------------------------------------------------------------------- - -local buffer_mt = -{ - lines = function(t) - return coroutine.wrap(function() - separated_values_iterator(t.buffer, t.parameters) - end) - end, - close = function(t) - if t.buffer.close then t.buffer:close() end - end, - name = function(t) - return t.parameters.filename - end, -} -buffer_mt.__index = buffer_mt - - ---- Use an existing file or buffer as a stream to read csv from. --- (A buffer is just something that looks like a string in that we can do --- `buffer:sub()` and `buffer:find()`) --- @return a file object -local function use( - buffer, -- ?string|file|buffer: the buffer to read from. If it's: - -- - a string, read from that; - -- - a file, turn it into a file_buffer; - -- - nil, read from stdin - -- otherwise assume it's already a a buffer. - parameters) -- ?table: parameters controlling reading the file. - -- See README.md - parameters = parameters or {} - parameters.filename = parameters.filename or "" - parameters.column_map = parameters.columns and - column_map:new(parameters.columns) - - if not buffer then - buffer = file_buffer:new(io.stdin) - elseif io.type(buffer) == "file" then - buffer = file_buffer:new(buffer) - end - - local f = { buffer = buffer, parameters = parameters } - return setmetatable(f, buffer_mt) -end - - ------------------------------------------------------------------------------- - ---- Open a file for reading as a delimited file --- @return a file object -local function open( - filename, -- string: name of the file to open - parameters) -- ?table: parameters controlling reading the file. - -- See README.md - local file, message = io.open(filename, "r") - if not file then return nil, message end - - parameters = parameters or {} - parameters.filename = filename - return use(file_buffer:new(file), parameters) -end - - ------------------------------------------------------------------------------- - -local function makename(s) - local t = {} - t[#t+1] = "<(String) " - t[#t+1] = (s:gmatch("[^\n]+")() or ""):sub(1,15) - if #t[#t] > 14 then t[#t+1] = "..." end - t[#t+1] = " >" - return table.concat(t) -end - - ---- Open a string for reading as a delimited file --- @return a file object -local function openstring( - filecontents, -- string: The contents of the delimited file - parameters) -- ?table: parameters controlling reading the file. - -- See README.md - - parameters = parameters or {} - - - parameters.filename = parameters.filename or makename(filecontents) - parameters.buffer_size = parameters.buffer_size or #filecontents - return use(filecontents, parameters) -end - - ------------------------------------------------------------------------------- - -return { open = open, openstring = openstring, use = use } - ------------------------------------------------------------------------------- diff --git a/Data/DefaultContent/Libraries/lua-csv/lua/test.lua b/Data/DefaultContent/Libraries/lua-csv/lua/test.lua deleted file mode 100644 index f418cf6..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/lua/test.lua +++ /dev/null @@ -1,102 +0,0 @@ -pcall(require, "strict") -local csv = require"csv" - -local errors = 0 - -local function testhandle(handle, correct_result) - local result = {} - for r in handle:lines() do - if not r[1] then - local r2 = {} - for k, v in pairs(r) do r2[#r2+1] = k..":"..tostring(v) end - table.sort(r2) - r = r2 - end - result[#result+1] = table.concat(r, ",") - end - - handle:close() - - result = table.concat(result, "!\n").."!" - if result ~= correct_result then - io.stderr:write( - ("Error reading '%s':\nExpected output:\n%s\n\nActual output:\n%s\n\n"): - format(handle:name(), correct_result, result)) - errors = errors + 1 - return false - end - return true -end - -local function test(filename, correct_result, parameters) - parameters = parameters or {} - for i = 1, 16 do - parameters.buffer_size = i - local f = csv.open(filename, parameters) - local fileok = testhandle(f, correct_result) - - if fileok then - f = io.open(filename, "r") - local data = f:read("*a") - f:close() - - f = csv.openstring(data, parameters) - testhandle(f, correct_result) - end - end -end - -test("../test-data/embedded-newlines.csv", [[ -embedded -newline,embedded -newline,embedded -newline! -embedded -newline,embedded -newline,embedded -newline!]]) - -test("../test-data/embedded-quotes.csv", [[ -embedded "quotes",embedded "quotes",embedded "quotes"! -embedded "quotes",embedded "quotes",embedded "quotes"!]]) - -test("../test-data/header.csv", [[ -alpha:ONE,bravo:two,charlie:3! -alpha:four,bravo:five,charlie:6!]], {header=true}) - -test("../test-data/header.csv", [[ -apple:one,charlie:30! -apple:four,charlie:60!]], -{ columns = { - apple = { name = "ALPHA", transform = string.lower }, - charlie = { transform = function(x) return tonumber(x) * 10 end }}}) - -test("../test-data/blank-line.csv", [[ -this,file,ends,with,a,blank,line!]]) - -test("../test-data/BOM.csv", [[ -apple:one,charlie:30! -apple:four,charlie:60!]], -{ columns = { - apple = { name = "ALPHA", transform = string.lower }, - charlie = { transform = function(x) return tonumber(x) * 10 end }}}) - -test("../test-data/bars.txt", [[ -there's a comma in this field, but no newline,embedded -newline,embedded -newline! -embedded -newline,embedded -newline,embedded -newline!]]) - - -if errors == 0 then - io.stdout:write("Passed\n") -elseif errors == 1 then - io.stdout:write("1 error\n") -else - io.stdout:write(("%d errors\n"):format(errors)) -end - -os.exit(errors) diff --git a/Data/DefaultContent/Libraries/lua-csv/makefile b/Data/DefaultContent/Libraries/lua-csv/makefile deleted file mode 100644 index dfa7596..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/makefile +++ /dev/null @@ -1,14 +0,0 @@ -LUA= $(shell echo `which lua`) -LUA_BINDIR= $(shell echo `dirname $(LUA)`) -LUA_PREFIX= $(shell echo `dirname $(LUA_BINDIR)`) -LUA_VERSION = $(shell echo `lua -v 2>&1 | cut -d " " -f 2 | cut -b 1-3`) -LUA_SHAREDIR=$(LUA_PREFIX)/share/lua/$(LUA_VERSION) - -default: - @echo "Nothing to build. Try 'make install' or 'make test'." - -install: - cp lua/csv.lua $(LUA_SHAREDIR) - -test: - cd lua && $(LUA) test.lua diff --git a/Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-1-1.rockspec b/Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-1-1.rockspec deleted file mode 100644 index 6f280aa..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-1-1.rockspec +++ /dev/null @@ -1,24 +0,0 @@ -package = "csv" -version = "1-1" -source = -{ - url = "git://github.com/geoffleyland/lua-csv.git", - branch = "master", - tag = "v1", -} -description = -{ - summary = "CSV and other delimited file reading", - homepage = "http://github.com/geoffleyland/lua-csv", - license = "MIT/X11", - maintainer = "Geoff Leyland " -} -dependencies = { "lua >= 5.1" } -build = -{ - type = "builtin", - modules = - { - csv = "lua/csv.lua", - }, -} diff --git a/Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec b/Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec deleted file mode 100644 index 29629da..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec +++ /dev/null @@ -1,23 +0,0 @@ -package = "csv" -version = "scm-1" -source = -{ - url = "git://github.com/geoffleyland/lua-csv.git", - branch = "master", -} -description = -{ - summary = "CSV and other delimited file reading", - homepage = "http://github.com/geoffleyland/lua-csv", - license = "MIT/X11", - maintainer = "Geoff Leyland " -} -dependencies = { "lua >= 5.1" } -build = -{ - type = "builtin", - modules = - { - csv = "lua/csv.lua", - }, -} diff --git a/Data/DefaultContent/Libraries/lua-csv/test-data/BOM.csv b/Data/DefaultContent/Libraries/lua-csv/test-data/BOM.csv deleted file mode 100644 index 9787c0d..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/test-data/BOM.csv +++ /dev/null @@ -1,3 +0,0 @@ -alpha,bravo,charlie -ONE,two,3 -four,five,6 \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/lua-csv/test-data/bars.txt b/Data/DefaultContent/Libraries/lua-csv/test-data/bars.txt deleted file mode 100644 index 9decabc..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/test-data/bars.txt +++ /dev/null @@ -1,7 +0,0 @@ -there's a comma in this field, but no newline|"embedded -newline"|"embedded -newline" -"embedded -newline"|"embedded -newline"|"embedded -newline" \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/lua-csv/test-data/blank-line.csv b/Data/DefaultContent/Libraries/lua-csv/test-data/blank-line.csv deleted file mode 100644 index 63fc515..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/test-data/blank-line.csv +++ /dev/null @@ -1,2 +0,0 @@ -this,file,ends,with,a,blank,line - diff --git a/Data/DefaultContent/Libraries/lua-csv/test-data/embedded-newlines.csv b/Data/DefaultContent/Libraries/lua-csv/test-data/embedded-newlines.csv deleted file mode 100644 index 67987d1..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/test-data/embedded-newlines.csv +++ /dev/null @@ -1,8 +0,0 @@ -"embedded -newline","embedded -newline","embedded -newline" -"embedded -newline","embedded -newline","embedded -newline" \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/lua-csv/test-data/embedded-quotes.csv b/Data/DefaultContent/Libraries/lua-csv/test-data/embedded-quotes.csv deleted file mode 100644 index e0c5c73..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/test-data/embedded-quotes.csv +++ /dev/null @@ -1,2 +0,0 @@ -"embedded ""quotes""","embedded ""quotes""","embedded ""quotes""" -"embedded ""quotes""","embedded ""quotes""","embedded ""quotes""" \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/lua-csv/test-data/header.csv b/Data/DefaultContent/Libraries/lua-csv/test-data/header.csv deleted file mode 100644 index 89f702e..0000000 --- a/Data/DefaultContent/Libraries/lua-csv/test-data/header.csv +++ /dev/null @@ -1,3 +0,0 @@ -alpha,bravo,charlie -ONE,two,3 -four,five,6 \ No newline at end of file diff --git a/Data/DefaultContent/Resources/Images/white.png b/Data/DefaultContent/Resources/Images/white.png new file mode 100644 index 0000000..ce5b789 Binary files /dev/null and b/Data/DefaultContent/Resources/Images/white.png differ diff --git a/Data/Libraries/GameLab/Editor/init.lua b/Data/Libraries/GameLab/Editor/init.lua index 99a8091..97b4b2e 100644 --- a/Data/Libraries/GameLab/Editor/init.lua +++ b/Data/Libraries/GameLab/Editor/init.lua @@ -1,2 +1,8 @@ +local m = GameLab.Editor or {} +GameLab.Editor = m +local import = GameLab.import(...) +m.AssetManager = import("AssetManager") + +return m \ No newline at end of file diff --git a/Data/Libraries/lua-csv/.gitignore b/Data/Libraries/lua-csv/.gitignore new file mode 100644 index 0000000..131f9b6 --- /dev/null +++ b/Data/Libraries/lua-csv/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +lua/docs \ No newline at end of file diff --git a/Data/Libraries/lua-csv/AUTHORS b/Data/Libraries/lua-csv/AUTHORS new file mode 100644 index 0000000..84961bd --- /dev/null +++ b/Data/Libraries/lua-csv/AUTHORS @@ -0,0 +1,2 @@ +Leyland, Geoff +Martin, Kevin diff --git a/Data/Libraries/lua-csv/LICENSE b/Data/Libraries/lua-csv/LICENSE new file mode 100644 index 0000000..d8472a0 --- /dev/null +++ b/Data/Libraries/lua-csv/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013-2014 Incremental IP Limited +Copyright (c) 2014 Kevin Martin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + diff --git a/Data/Libraries/lua-csv/README.md b/Data/Libraries/lua-csv/README.md new file mode 100644 index 0000000..d10314a --- /dev/null +++ b/Data/Libraries/lua-csv/README.md @@ -0,0 +1,93 @@ +# Lua-CSV - delimited file reading + +## 1. What? + +Lua-CSV is a Lua module for reading delimited text files (popularly CSV and +tab-separated files, but you can specify the separator). + +Lua-CSV tries to auto-detect whether a file is delimited with commas or tabs, +copes with non-native newlines, survives newlines and quotes inside quoted +fields and offers an iterator interface so it can handle large files. + + +## 2. How? + + local csv = require("csv") + local f = csv.open("file.csv") + for fields in f:lines() do + for i, v in ipairs(fields) do print(i, v) end + end + +`csv.open` takes a second argument `parameters`, a table of parameters +controlling how the file is read: + ++ `separator` sets the separator. It'll probably guess the separator + correctly if it's a comma or a tab (unless, say, the first field in a + tab-delimited file contains a comma), but if you want something else you'll + have to set this. It could be more than one character, but it's used as + part of a set: `"["..sep.."\n\r]"` + ++ Set `header` to true if the file contains a header and each set of fields + will be keyed by the names in the header rather than by integer index. + ++ `columns` provides a mechanism for column remapping. + Suppose you have a csv file as follows: + + Word,Number + ONE,10 + + And columns is: + + + `{ word = true }` then the only field in the file would be + `{ word = "ONE" }` + + `{ first = { name = "word"} }` then it would be `{ first = "ONE" }` + + `{ word = { transform = string.lower }}` would give `{ word = "one" }` + + finally, + + { word = true + number = { transform = function(x) return tonumber(x) / 10 end }} + + would give `{ word = "ONE", number = 1 }` + + A column can have more than one name: + `{ first = { names = {"word", "worm"}}}` to help cope with badly specified + file formats and spelling mistakes. + ++ `buffer_size` controls the size of the blocks the file is read in. The + default is 1MB. It used to be 4096 bytes which is what `pagesize` says on + my system, but that seems kind of small. + +`csv.openstring` works exactly like `csv.open` except the first argument +is the contents of the csv file. In this case `buffer_size` is set to +the length of the string. + +## 3. Requirements + +Lua 5.1, 5.2 or LuaJIT. + + +## 4. Issues + ++ Some whitespace-delimited files might use more than one space between + fields, for example if the columns are "manually" aligned: + + street nr city + "Oneway Street" 1 Toontown + + It won't cope with this - you'll get lots of extra empty fields. + +## 5. Wishlist + ++ Tests would be nice. ++ So would better LDoc documentation. + + +## 6. Alternatives + ++ [Penlight](http://github.com/stevedonovan/penlight) contains delimited + file reading. It reads the whole file in one go. ++ The Lua Wiki contains two pages on CSV + [here](http://lua-users.org/wiki/LuaCsv) and + [here](http://lua-users.org/wiki/CsvUtils). ++ There's an example using [LPeg](http://www.inf.puc-rio.br/~roberto/lpeg/) + to parse CSV [here](http://www.inf.puc-rio.br/~roberto/lpeg/#CSV) diff --git a/Data/Libraries/lua-csv/lua/config.ld b/Data/Libraries/lua-csv/lua/config.ld new file mode 100644 index 0000000..af51949 --- /dev/null +++ b/Data/Libraries/lua-csv/lua/config.ld @@ -0,0 +1,4 @@ +project = "Lua-CSV" +title = "Lua-CSV Source Documentation" +description = "Lua-CSV reads delimited text files" +format = "markdown" diff --git a/Data/Libraries/lua-csv/lua/csv.lua b/Data/Libraries/lua-csv/lua/csv.lua new file mode 100644 index 0000000..64196c0 --- /dev/null +++ b/Data/Libraries/lua-csv/lua/csv.lua @@ -0,0 +1,557 @@ +--- Read a comma or tab (or other delimiter) separated file. +-- This version of a CSV reader differs from others I've seen in that it +-- +-- + handles embedded newlines in fields (if they're delimited with double +-- quotes) +-- + is line-ending agnostic +-- + reads the file line-by-line, so it can potientially handle large +-- files. +-- +-- Of course, for such a simple format, CSV is horribly complicated, so it +-- likely gets something wrong. + +-- (c) Copyright 2013-2014 Incremental IP Limited. +-- (c) Copyright 2014 Kevin Martin +-- Available under the MIT licence. See LICENSE for more information. + +local DEFAULT_BUFFER_BLOCK_SIZE = 1024 * 1024 + + +------------------------------------------------------------------------------ + +local function trim_space(s) + return s:match("^%s*(.-)%s*$") +end + + +local function fix_quotes(s) + -- the sub(..., -2) is to strip the trailing quote + return string.sub(s:gsub('""', '"'), 1, -2) +end + + +------------------------------------------------------------------------------ + +local column_map = {} +column_map.__index = column_map + + +local function normalise_string(s) + return (s:lower():gsub("[^%w%d]+", " "):gsub("^ *(.-) *$", "%1")) +end + + +--- Parse a list of columns. +-- The main job here is normalising column names and dealing with columns +-- for which we have more than one possible name in the header. +function column_map:new(columns) + local name_map = {} + for n, v in pairs(columns) do + local names + local t + if type(v) == "table" then + t = { transform = v.transform, default = v.default } + if v.name then + names = { normalise_string(v.name) } + elseif v.names then + names = v.names + for i, n in ipairs(names) do names[i] = normalise_string(n) end + end + else + if type(v) == "function" then + t = { transform = v } + else + t = {} + if type(v) == "string" then + names = { normalise_string(v) } + end + end + end + + if not names then + names = { (n:lower():gsub("[^%w%d]+", " ")) } + end + + t.name = n + for _, n in ipairs(names) do + name_map[n:lower()] = t + end + end + + return setmetatable({ name_map = name_map }, column_map) +end + + +--- Map "virtual" columns to file columns. +-- Once we've read the header, work out which columns we're interested in and +-- what to do with them. Mostly this is about checking we've got the columns +-- we need and writing a nice complaint if we haven't. +function column_map:read_header(header) + local index_map = {} + + -- Match the columns in the file to the columns in the name map + local found = {} + local found_any + for i, word in ipairs(header) do + word = normalise_string(word) + local r = self.name_map[word] + if r then + index_map[i] = r + found[r.name] = true + found_any = true + end + end + + if not found_any then return end + + -- check we found all the columns we need + local not_found = {} + for name, r in pairs(self.name_map) do + if not found[r.name] then + local nf = not_found[r.name] + if nf then + nf[#nf+1] = name + else + not_found[r.name] = { name } + end + end + end + -- If any columns are missing, assemble an error message + if next(not_found) then + local problems = {} + for k, v in pairs(not_found) do + local missing + if #v == 1 then + missing = "'"..v[1].."'" + else + missing = v[1] + for i = 2, #v - 1 do + missing = missing..", '"..v[i].."'" + end + missing = missing.." or '"..v[#v].."'" + end + problems[#problems+1] = "Couldn't find a column named "..missing + end + error(table.concat(problems, "\n"), 0) + end + + self.index_map = index_map + return true +end + + +function column_map:transform(value, index) + local field = self.index_map[index] + if field then + if field.transform then + local ok + ok, value = pcall(field.transform, value) + if not ok then + error(("Error reading field '%s': %s"):format(field.name, value), 0) + end + end + return value or field.default, field.name + end +end + + +------------------------------------------------------------------------------ + +local file_buffer = {} +file_buffer.__index = file_buffer + +function file_buffer:new(file, buffer_block_size) + return setmetatable({ + file = file, + buffer_block_size = buffer_block_size or DEFAULT_BUFFER_BLOCK_SIZE, + buffer_start = 0, + buffer = "", + }, file_buffer) +end + + +--- Cut the front off the buffer if we've already read it +function file_buffer:truncate(p) + p = p - self.buffer_start + if p > self.buffer_block_size then + local remove = self.buffer_block_size * + math.floor((p-1) / self.buffer_block_size) + self.buffer = self.buffer:sub(remove + 1) + self.buffer_start = self.buffer_start + remove + end +end + + +--- Find something in the buffer, extending it if necessary +function file_buffer:find(pattern, init) + while true do + local first, last, capture = + self.buffer:find(pattern, init - self.buffer_start) + -- if we found nothing, or the last character is at the end of the + -- buffer (and the match could potentially be longer) then read some + -- more. + if not first or last == #self.buffer then + local s = self.file:read(self.buffer_block_size) + if not s then + if not first then + return + else + return first + self.buffer_start, last + self.buffer_start, capture + end + end + self.buffer = self.buffer..s + else + return first + self.buffer_start, last + self.buffer_start, capture + end + end +end + + +--- Extend the buffer so we can see more +function file_buffer:extend(offset) + local extra = offset - #self.buffer - self.buffer_start + if extra > 0 then + local size = self.buffer_block_size * + math.ceil(extra / self.buffer_block_size) + local s = self.file:read(size) + if not s then return end + self.buffer = self.buffer..s + end +end + + +--- Get a substring from the buffer, extending it if necessary +function file_buffer:sub(a, b) + self:extend(b) + b = b == -1 and b or b - self.buffer_start + return self.buffer:sub(a - self.buffer_start, b) +end + + +--- Close a file buffer +function file_buffer:close() + self.file:close() + self.file = nil +end + + +------------------------------------------------------------------------------ + +local separator_candidates = { ",", "\t", "|" } +local guess_separator_params = { record_limit = 8; } + + +local function try_separator(buffer, sep, f) + guess_separator_params.separator = sep + local min, max = math.huge, 0 + local lines, split_lines = 0, 0 + local iterator = coroutine.wrap(function() f(buffer, guess_separator_params) end) + for t in iterator do + min = math.min(min, #t) + max = math.max(max, #t) + split_lines = split_lines + (t[2] and 1 or 0) + lines = lines + 1 + end + if split_lines / lines > 0.75 then + return max - min + else + return math.huge + end +end + + +--- If the user hasn't specified a separator, try to work out what it is. +function guess_separator(buffer, f) + local best_separator, lowest_diff = "", math.huge + for _, s in ipairs(separator_candidates) do + local ok, diff = pcall(function() return try_separator(buffer, s, f) end) + if ok and diff < lowest_diff then + best_separator = s + lowest_diff = diff + end + end + + return best_separator +end + + +local unicode_BOMS = +{ + { + length = 2, + BOMS = + { + ["\254\255"] = true, -- UTF-16 big-endian + ["\255\254"] = true, -- UTF-16 little-endian + } + }, + { + length = 3, + BOMS = + { + ["\239\187\191"] = true, -- UTF-8 + } + } +} + + +local function find_unicode_BOM(sub) + for _, x in ipairs(unicode_BOMS) do + local code = sub(1, x.length) + if x.BOMS[code] then + return x.length + end + end + return 0 +end + + +--- Iterate through the records in a file +-- Since records might be more than one line (if there's a newline in quotes) +-- and line-endings might not be native, we read the file in chunks of +-- we read the file in chunks using a file_buffer, rather than line-by-line +-- using io.lines. +local function separated_values_iterator(buffer, parameters) + local field_start = 1 + + local advance + if buffer.truncate then + advance = function(n) + field_start = field_start + n + buffer:truncate(field_start) + end + else + advance = function(n) + field_start = field_start + n + end + end + + + local function field_sub(a, b) + b = b == -1 and b or b + field_start - 1 + return buffer:sub(a + field_start - 1, b) + end + + + local function field_find(pattern, init) + init = init or 1 + local f, l, c = buffer:find(pattern, init + field_start - 1) + if not f then return end + return f - field_start + 1, l - field_start + 1, c + end + + + -- Is there some kind of Unicode BOM here? + advance(find_unicode_BOM(field_sub)) + + + -- Start reading the file + local sep = "(["..(parameters.separator or + guess_separator(buffer, separated_values_iterator)).."\n\r])" + local line_start = 1 + local line = 1 + local field_count, fields, starts, nonblanks = 0, {}, {} + local header, header_read + local field_start_line, field_start_column + local record_count = 0 + + + local function problem(message) + error(("%s:%d:%d: %s"): + format(parameters.filename, field_start_line, field_start_column, + message), 0) + end + + + while true do + local field_end, sep_end, this_sep + local tidy + field_start_line = line + field_start_column = field_start - line_start + 1 + + -- If the field is quoted, go find the other quote + if field_sub(1, 1) == '"' then + advance(1) + local current_pos = 0 + repeat + local a, b, c = field_find('"("?)', current_pos + 1) + current_pos = b + until c ~= '"' + if not current_pos then problem("unmatched quote") end + tidy = fix_quotes + field_end, sep_end, this_sep = field_find(" *([^ ])", current_pos+1) + if this_sep and not this_sep:match(sep) then problem("unmatched quote") end + else + field_end, sep_end, this_sep = field_find(sep, 1) + tidy = trim_space + end + + -- Look for the separator or a newline or the end of the file + field_end = (field_end or 0) - 1 + + -- Read the field, then convert all the line endings to \n, and + -- count any embedded line endings + local value = field_sub(1, field_end) + value = value:gsub("\r\n", "\n"):gsub("\r", "\n") + for nl in value:gmatch("\n()") do + line = line + 1 + line_start = nl + field_start + end + + value = tidy(value) + if #value > 0 then nonblanks = true end + field_count = field_count + 1 + + -- Insert the value into the table for this "line" + local key + if parameters.column_map and header_read then + local ok + ok, value, key = pcall(parameters.column_map.transform, + parameters.column_map, value, field_count) + if not ok then problem(value) end + elseif header then + key = header[field_count] + else + key = field_count + end + if key then + fields[key] = value + starts[key] = { line=field_start_line, column=field_start_column } + end + + -- if we ended on a newline then yield the fields on this line. + if not this_sep or this_sep == "\r" or this_sep == "\n" then + if parameters.column_map and not header_read then + header_read = parameters.column_map:read_header(fields) + elseif parameters.header and not header_read then + if nonblanks or field_count > 1 then -- ignore blank lines + header = fields + header_read = true + end + else + if nonblanks or field_count > 1 then -- ignore blank lines + coroutine.yield(fields, starts) + record_count = record_count + 1 + if parameters.record_limit and + record_count >= parameters.record_limit then + break + end + end + end + field_count, fields, starts, nonblanks = 0, {}, {} + end + + -- If we *really* didn't find a separator then we're done. + if not sep_end then break end + + -- If we ended on a newline then count it. + if this_sep == "\r" or this_sep == "\n" then + if this_sep == "\r" and field_sub(sep_end+1, sep_end+1) == "\n" then + sep_end = sep_end + 1 + end + line = line + 1 + line_start = field_start + sep_end + end + + advance(sep_end) + end +end + + +------------------------------------------------------------------------------ + +local buffer_mt = +{ + lines = function(t) + return coroutine.wrap(function() + separated_values_iterator(t.buffer, t.parameters) + end) + end, + close = function(t) + if t.buffer.close then t.buffer:close() end + end, + name = function(t) + return t.parameters.filename + end, +} +buffer_mt.__index = buffer_mt + + +--- Use an existing file or buffer as a stream to read csv from. +-- (A buffer is just something that looks like a string in that we can do +-- `buffer:sub()` and `buffer:find()`) +-- @return a file object +local function use( + buffer, -- ?string|file|buffer: the buffer to read from. If it's: + -- - a string, read from that; + -- - a file, turn it into a file_buffer; + -- - nil, read from stdin + -- otherwise assume it's already a a buffer. + parameters) -- ?table: parameters controlling reading the file. + -- See README.md + parameters = parameters or {} + parameters.filename = parameters.filename or "" + parameters.column_map = parameters.columns and + column_map:new(parameters.columns) + + if not buffer then + buffer = file_buffer:new(io.stdin) + elseif io.type(buffer) == "file" then + buffer = file_buffer:new(buffer) + end + + local f = { buffer = buffer, parameters = parameters } + return setmetatable(f, buffer_mt) +end + + +------------------------------------------------------------------------------ + +--- Open a file for reading as a delimited file +-- @return a file object +local function open( + filename, -- string: name of the file to open + parameters) -- ?table: parameters controlling reading the file. + -- See README.md + local file, message = io.open(filename, "r") + if not file then return nil, message end + + parameters = parameters or {} + parameters.filename = filename + return use(file_buffer:new(file), parameters) +end + + +------------------------------------------------------------------------------ + +local function makename(s) + local t = {} + t[#t+1] = "<(String) " + t[#t+1] = (s:gmatch("[^\n]+")() or ""):sub(1,15) + if #t[#t] > 14 then t[#t+1] = "..." end + t[#t+1] = " >" + return table.concat(t) +end + + +--- Open a string for reading as a delimited file +-- @return a file object +local function openstring( + filecontents, -- string: The contents of the delimited file + parameters) -- ?table: parameters controlling reading the file. + -- See README.md + + parameters = parameters or {} + + + parameters.filename = parameters.filename or makename(filecontents) + parameters.buffer_size = parameters.buffer_size or #filecontents + return use(filecontents, parameters) +end + + +------------------------------------------------------------------------------ + +return { open = open, openstring = openstring, use = use } + +------------------------------------------------------------------------------ diff --git a/Data/Libraries/lua-csv/lua/test.lua b/Data/Libraries/lua-csv/lua/test.lua new file mode 100644 index 0000000..f418cf6 --- /dev/null +++ b/Data/Libraries/lua-csv/lua/test.lua @@ -0,0 +1,102 @@ +pcall(require, "strict") +local csv = require"csv" + +local errors = 0 + +local function testhandle(handle, correct_result) + local result = {} + for r in handle:lines() do + if not r[1] then + local r2 = {} + for k, v in pairs(r) do r2[#r2+1] = k..":"..tostring(v) end + table.sort(r2) + r = r2 + end + result[#result+1] = table.concat(r, ",") + end + + handle:close() + + result = table.concat(result, "!\n").."!" + if result ~= correct_result then + io.stderr:write( + ("Error reading '%s':\nExpected output:\n%s\n\nActual output:\n%s\n\n"): + format(handle:name(), correct_result, result)) + errors = errors + 1 + return false + end + return true +end + +local function test(filename, correct_result, parameters) + parameters = parameters or {} + for i = 1, 16 do + parameters.buffer_size = i + local f = csv.open(filename, parameters) + local fileok = testhandle(f, correct_result) + + if fileok then + f = io.open(filename, "r") + local data = f:read("*a") + f:close() + + f = csv.openstring(data, parameters) + testhandle(f, correct_result) + end + end +end + +test("../test-data/embedded-newlines.csv", [[ +embedded +newline,embedded +newline,embedded +newline! +embedded +newline,embedded +newline,embedded +newline!]]) + +test("../test-data/embedded-quotes.csv", [[ +embedded "quotes",embedded "quotes",embedded "quotes"! +embedded "quotes",embedded "quotes",embedded "quotes"!]]) + +test("../test-data/header.csv", [[ +alpha:ONE,bravo:two,charlie:3! +alpha:four,bravo:five,charlie:6!]], {header=true}) + +test("../test-data/header.csv", [[ +apple:one,charlie:30! +apple:four,charlie:60!]], +{ columns = { + apple = { name = "ALPHA", transform = string.lower }, + charlie = { transform = function(x) return tonumber(x) * 10 end }}}) + +test("../test-data/blank-line.csv", [[ +this,file,ends,with,a,blank,line!]]) + +test("../test-data/BOM.csv", [[ +apple:one,charlie:30! +apple:four,charlie:60!]], +{ columns = { + apple = { name = "ALPHA", transform = string.lower }, + charlie = { transform = function(x) return tonumber(x) * 10 end }}}) + +test("../test-data/bars.txt", [[ +there's a comma in this field, but no newline,embedded +newline,embedded +newline! +embedded +newline,embedded +newline,embedded +newline!]]) + + +if errors == 0 then + io.stdout:write("Passed\n") +elseif errors == 1 then + io.stdout:write("1 error\n") +else + io.stdout:write(("%d errors\n"):format(errors)) +end + +os.exit(errors) diff --git a/Data/Libraries/lua-csv/makefile b/Data/Libraries/lua-csv/makefile new file mode 100644 index 0000000..dfa7596 --- /dev/null +++ b/Data/Libraries/lua-csv/makefile @@ -0,0 +1,14 @@ +LUA= $(shell echo `which lua`) +LUA_BINDIR= $(shell echo `dirname $(LUA)`) +LUA_PREFIX= $(shell echo `dirname $(LUA_BINDIR)`) +LUA_VERSION = $(shell echo `lua -v 2>&1 | cut -d " " -f 2 | cut -b 1-3`) +LUA_SHAREDIR=$(LUA_PREFIX)/share/lua/$(LUA_VERSION) + +default: + @echo "Nothing to build. Try 'make install' or 'make test'." + +install: + cp lua/csv.lua $(LUA_SHAREDIR) + +test: + cd lua && $(LUA) test.lua diff --git a/Data/Libraries/lua-csv/rockspecs/csv-1-1.rockspec b/Data/Libraries/lua-csv/rockspecs/csv-1-1.rockspec new file mode 100644 index 0000000..6f280aa --- /dev/null +++ b/Data/Libraries/lua-csv/rockspecs/csv-1-1.rockspec @@ -0,0 +1,24 @@ +package = "csv" +version = "1-1" +source = +{ + url = "git://github.com/geoffleyland/lua-csv.git", + branch = "master", + tag = "v1", +} +description = +{ + summary = "CSV and other delimited file reading", + homepage = "http://github.com/geoffleyland/lua-csv", + license = "MIT/X11", + maintainer = "Geoff Leyland " +} +dependencies = { "lua >= 5.1" } +build = +{ + type = "builtin", + modules = + { + csv = "lua/csv.lua", + }, +} diff --git a/Data/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec b/Data/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec new file mode 100644 index 0000000..29629da --- /dev/null +++ b/Data/Libraries/lua-csv/rockspecs/csv-scm-1.rockspec @@ -0,0 +1,23 @@ +package = "csv" +version = "scm-1" +source = +{ + url = "git://github.com/geoffleyland/lua-csv.git", + branch = "master", +} +description = +{ + summary = "CSV and other delimited file reading", + homepage = "http://github.com/geoffleyland/lua-csv", + license = "MIT/X11", + maintainer = "Geoff Leyland " +} +dependencies = { "lua >= 5.1" } +build = +{ + type = "builtin", + modules = + { + csv = "lua/csv.lua", + }, +} diff --git a/Data/Libraries/lua-csv/test-data/BOM.csv b/Data/Libraries/lua-csv/test-data/BOM.csv new file mode 100644 index 0000000..9787c0d --- /dev/null +++ b/Data/Libraries/lua-csv/test-data/BOM.csv @@ -0,0 +1,3 @@ +alpha,bravo,charlie +ONE,two,3 +four,five,6 \ No newline at end of file diff --git a/Data/Libraries/lua-csv/test-data/bars.txt b/Data/Libraries/lua-csv/test-data/bars.txt new file mode 100644 index 0000000..9decabc --- /dev/null +++ b/Data/Libraries/lua-csv/test-data/bars.txt @@ -0,0 +1,7 @@ +there's a comma in this field, but no newline|"embedded +newline"|"embedded +newline" +"embedded +newline"|"embedded +newline"|"embedded +newline" \ No newline at end of file diff --git a/Data/Libraries/lua-csv/test-data/blank-line.csv b/Data/Libraries/lua-csv/test-data/blank-line.csv new file mode 100644 index 0000000..63fc515 --- /dev/null +++ b/Data/Libraries/lua-csv/test-data/blank-line.csv @@ -0,0 +1,2 @@ +this,file,ends,with,a,blank,line + diff --git a/Data/Libraries/lua-csv/test-data/embedded-newlines.csv b/Data/Libraries/lua-csv/test-data/embedded-newlines.csv new file mode 100644 index 0000000..67987d1 --- /dev/null +++ b/Data/Libraries/lua-csv/test-data/embedded-newlines.csv @@ -0,0 +1,8 @@ +"embedded +newline","embedded +newline","embedded +newline" +"embedded +newline","embedded +newline","embedded +newline" \ No newline at end of file diff --git a/Data/Libraries/lua-csv/test-data/embedded-quotes.csv b/Data/Libraries/lua-csv/test-data/embedded-quotes.csv new file mode 100644 index 0000000..e0c5c73 --- /dev/null +++ b/Data/Libraries/lua-csv/test-data/embedded-quotes.csv @@ -0,0 +1,2 @@ +"embedded ""quotes""","embedded ""quotes""","embedded ""quotes""" +"embedded ""quotes""","embedded ""quotes""","embedded ""quotes""" \ No newline at end of file diff --git a/Data/Libraries/lua-csv/test-data/header.csv b/Data/Libraries/lua-csv/test-data/header.csv new file mode 100644 index 0000000..89f702e --- /dev/null +++ b/Data/Libraries/lua-csv/test-data/header.csv @@ -0,0 +1,3 @@ +alpha,bravo,charlie +ONE,two,3 +four,five,6 \ No newline at end of file diff --git a/Data/Resources/Gizmos/Gizmos.xlsx b/Data/Resources/Gizmos/Gizmos.xlsx deleted file mode 100644 index cb921d4..0000000 Binary files a/Data/Resources/Gizmos/Gizmos.xlsx and /dev/null differ diff --git a/Data/Resources/Icons/buttons/add.png b/Data/Resources/Icons/buttons/add.png new file mode 100644 index 0000000..332a030 Binary files /dev/null and b/Data/Resources/Icons/buttons/add.png differ diff --git a/Data/Resources/Icons/buttons/alpha.png b/Data/Resources/Icons/buttons/alpha.png new file mode 100644 index 0000000..207c18b Binary files /dev/null and b/Data/Resources/Icons/buttons/alpha.png differ diff --git a/Data/Resources/Icons/buttons/checker.png b/Data/Resources/Icons/buttons/checker.png new file mode 100644 index 0000000..f6c3f0f Binary files /dev/null and b/Data/Resources/Icons/buttons/checker.png differ diff --git a/Data/Resources/Icons/buttons/cog.png b/Data/Resources/Icons/buttons/cog.png new file mode 100644 index 0000000..5cf1e16 Binary files /dev/null and b/Data/Resources/Icons/buttons/cog.png differ diff --git a/Data/Resources/Icons/buttons/del.png b/Data/Resources/Icons/buttons/del.png new file mode 100644 index 0000000..34a9b5a Binary files /dev/null and b/Data/Resources/Icons/buttons/del.png differ diff --git a/Data/Resources/Icons/buttons/del2.png b/Data/Resources/Icons/buttons/del2.png new file mode 100644 index 0000000..22cb0d3 Binary files /dev/null and b/Data/Resources/Icons/buttons/del2.png differ diff --git a/Data/Resources/Icons/buttons/del3.png b/Data/Resources/Icons/buttons/del3.png new file mode 100644 index 0000000..16d30d1 Binary files /dev/null and b/Data/Resources/Icons/buttons/del3.png differ diff --git a/Data/Resources/Icons/buttons/delete.png b/Data/Resources/Icons/buttons/delete.png new file mode 100644 index 0000000..31da2d8 Binary files /dev/null and b/Data/Resources/Icons/buttons/delete.png differ diff --git a/Data/Resources/Icons/buttons/disable.png b/Data/Resources/Icons/buttons/disable.png new file mode 100644 index 0000000..cfdc3da Binary files /dev/null and b/Data/Resources/Icons/buttons/disable.png differ diff --git a/Data/Resources/Icons/buttons/down.png b/Data/Resources/Icons/buttons/down.png new file mode 100644 index 0000000..3fe5bf0 Binary files /dev/null and b/Data/Resources/Icons/buttons/down.png differ diff --git a/Data/Resources/Icons/buttons/forward.png b/Data/Resources/Icons/buttons/forward.png new file mode 100644 index 0000000..ee986ea Binary files /dev/null and b/Data/Resources/Icons/buttons/forward.png differ diff --git a/Data/Resources/Icons/buttons/invisible.png b/Data/Resources/Icons/buttons/invisible.png new file mode 100644 index 0000000..a5a1f55 Binary files /dev/null and b/Data/Resources/Icons/buttons/invisible.png differ diff --git a/Data/Resources/Icons/buttons/lock.png b/Data/Resources/Icons/buttons/lock.png new file mode 100644 index 0000000..e5ae209 Binary files /dev/null and b/Data/Resources/Icons/buttons/lock.png differ diff --git a/Data/Resources/Icons/buttons/open.png b/Data/Resources/Icons/buttons/open.png new file mode 100644 index 0000000..178b46b Binary files /dev/null and b/Data/Resources/Icons/buttons/open.png differ diff --git a/Data/Resources/Icons/buttons/pause.png b/Data/Resources/Icons/buttons/pause.png new file mode 100644 index 0000000..380f5a1 Binary files /dev/null and b/Data/Resources/Icons/buttons/pause.png differ diff --git a/Data/Resources/Icons/buttons/pen.png b/Data/Resources/Icons/buttons/pen.png new file mode 100644 index 0000000..3707dd5 Binary files /dev/null and b/Data/Resources/Icons/buttons/pen.png differ diff --git a/Data/Resources/Icons/buttons/play.png b/Data/Resources/Icons/buttons/play.png new file mode 100644 index 0000000..bcf2bae Binary files /dev/null and b/Data/Resources/Icons/buttons/play.png differ diff --git a/Data/Resources/Icons/buttons/play2.png b/Data/Resources/Icons/buttons/play2.png new file mode 100644 index 0000000..fadfed2 Binary files /dev/null and b/Data/Resources/Icons/buttons/play2.png differ diff --git a/Data/Resources/Icons/buttons/pop_disabled.png b/Data/Resources/Icons/buttons/pop_disabled.png new file mode 100644 index 0000000..72b38d5 Binary files /dev/null and b/Data/Resources/Icons/buttons/pop_disabled.png differ diff --git a/Data/Resources/Icons/buttons/pop_hover.png b/Data/Resources/Icons/buttons/pop_hover.png new file mode 100644 index 0000000..b9518e8 Binary files /dev/null and b/Data/Resources/Icons/buttons/pop_hover.png differ diff --git a/Data/Resources/Icons/buttons/pop_normal.png b/Data/Resources/Icons/buttons/pop_normal.png new file mode 100644 index 0000000..63ef8d0 Binary files /dev/null and b/Data/Resources/Icons/buttons/pop_normal.png differ diff --git a/Data/Resources/Icons/buttons/pop_selected.png b/Data/Resources/Icons/buttons/pop_selected.png new file mode 100644 index 0000000..a26b9b3 Binary files /dev/null and b/Data/Resources/Icons/buttons/pop_selected.png differ diff --git a/Data/Resources/Icons/buttons/prefab_apply.png b/Data/Resources/Icons/buttons/prefab_apply.png new file mode 100644 index 0000000..0b35e92 Binary files /dev/null and b/Data/Resources/Icons/buttons/prefab_apply.png differ diff --git a/Data/Resources/Icons/buttons/prefab_revert.png b/Data/Resources/Icons/buttons/prefab_revert.png new file mode 100644 index 0000000..bc47649 Binary files /dev/null and b/Data/Resources/Icons/buttons/prefab_revert.png differ diff --git a/Data/Resources/Icons/buttons/rgb.png b/Data/Resources/Icons/buttons/rgb.png new file mode 100644 index 0000000..710a6cf Binary files /dev/null and b/Data/Resources/Icons/buttons/rgb.png differ diff --git a/Data/Resources/Icons/buttons/search.png b/Data/Resources/Icons/buttons/search.png new file mode 100644 index 0000000..843fc7a Binary files /dev/null and b/Data/Resources/Icons/buttons/search.png differ diff --git a/Data/Resources/Icons/buttons/smalladd.png b/Data/Resources/Icons/buttons/smalladd.png new file mode 100644 index 0000000..bb3b03a Binary files /dev/null and b/Data/Resources/Icons/buttons/smalladd.png differ diff --git a/Data/Resources/Icons/buttons/smalldel.png b/Data/Resources/Icons/buttons/smalldel.png new file mode 100644 index 0000000..aafffd4 Binary files /dev/null and b/Data/Resources/Icons/buttons/smalldel.png differ diff --git a/Data/Resources/Icons/buttons/smalldisable.png b/Data/Resources/Icons/buttons/smalldisable.png new file mode 100644 index 0000000..b1d5999 Binary files /dev/null and b/Data/Resources/Icons/buttons/smalldisable.png differ diff --git a/Data/Resources/Icons/buttons/smalldisableempty.png b/Data/Resources/Icons/buttons/smalldisableempty.png new file mode 100644 index 0000000..ce5068f Binary files /dev/null and b/Data/Resources/Icons/buttons/smalldisableempty.png differ diff --git a/Data/Resources/Icons/buttons/smalllock.png b/Data/Resources/Icons/buttons/smalllock.png new file mode 100644 index 0000000..9716287 Binary files /dev/null and b/Data/Resources/Icons/buttons/smalllock.png differ diff --git a/Data/Resources/Icons/buttons/star.png b/Data/Resources/Icons/buttons/star.png new file mode 100644 index 0000000..c8b11f5 Binary files /dev/null and b/Data/Resources/Icons/buttons/star.png differ diff --git a/Data/Resources/Icons/buttons/stopplay.png b/Data/Resources/Icons/buttons/stopplay.png new file mode 100644 index 0000000..bfe1897 Binary files /dev/null and b/Data/Resources/Icons/buttons/stopplay.png differ diff --git a/Data/Resources/Icons/buttons/up.png b/Data/Resources/Icons/buttons/up.png new file mode 100644 index 0000000..75713f0 Binary files /dev/null and b/Data/Resources/Icons/buttons/up.png differ diff --git a/Data/Resources/Images/UI.csv b/Data/Resources/Images/UI.csv deleted file mode 100644 index e9c9eea..0000000 --- a/Data/Resources/Images/UI.csv +++ /dev/null @@ -1,2 +0,0 @@ -filePath type slice left right top bottom -asdasd diff --git a/Data/Resources/Images/UI.xlsx b/Data/Resources/Images/UI.xlsx deleted file mode 100644 index 15e2235..0000000 Binary files a/Data/Resources/Images/UI.xlsx and /dev/null differ diff --git a/Data/Resources/Images/brickwall.jpg b/Data/Resources/Images/brickwall.jpg new file mode 100644 index 0000000..39478d3 Binary files /dev/null and b/Data/Resources/Images/brickwall.jpg differ diff --git a/Data/Resources/Metatable/Excel/Extract_All.cmd b/Data/Resources/Metatable/Excel/Extract_All.cmd index f6dd7d2..8cd629f 100644 --- a/Data/Resources/Metatable/Excel/Extract_All.cmd +++ b/Data/Resources/Metatable/Excel/Extract_All.cmd @@ -1,2 +1,3 @@ ./Extract_Gizmos.cmd -./Extract_Icons.cmd \ No newline at end of file +./Extract_Icons.cmd +./Extract_Shaders.cmd \ No newline at end of file diff --git a/Data/Resources/Metatable/Excel/Extract_Shaders.cmd b/Data/Resources/Metatable/Excel/Extract_Shaders.cmd new file mode 100644 index 0000000..312000b --- /dev/null +++ b/Data/Resources/Metatable/Excel/Extract_Shaders.cmd @@ -0,0 +1 @@ +"../../../../Tools/XlsxToCsv/xlsxToCsv.exe" Shaders.xlsx ../Shaders.csv \ No newline at end of file diff --git a/Data/Resources/Metatable/Excel/Icons.xlsx b/Data/Resources/Metatable/Excel/Icons.xlsx index 501ae81..bc359e5 100644 Binary files a/Data/Resources/Metatable/Excel/Icons.xlsx and b/Data/Resources/Metatable/Excel/Icons.xlsx differ diff --git a/Data/Resources/Metatable/Excel/Shaders.xlsx b/Data/Resources/Metatable/Excel/Shaders.xlsx new file mode 100644 index 0000000..3dcafa2 Binary files /dev/null and b/Data/Resources/Metatable/Excel/Shaders.xlsx differ diff --git a/Data/Resources/Metatable/Icons.csv b/Data/Resources/Metatable/Icons.csv index 04cb8d7..0b7221a 100644 --- a/Data/Resources/Metatable/Icons.csv +++ b/Data/Resources/Metatable/Icons.csv @@ -1,8 +1,7 @@ -Path,Type,Left,Right,Top,Bottom, -UI.png,1,12,12,13,13, -UI.png,1,12,12,13,13, -UI.png,1,12,12,13,13, -UI.png,1,12,12,13,13, -UI.png,1,12,12,13,13, -UI.png,1,12,12,13,13, -UI.png,1,12,12,13,13, +Name,Category,Path,Filter,Wrap,Slicing,Left,Right,Top,Bottom, +btn_add,Button,buttons/add.png,,,,,,,, +btn_alpha,Button,buttons/alpha.png,,,,,,,, +btn_checker,Button,buttons/checker.png,,,,,,,, +,,,,,,,,,, +,,,,,,,,,, +,,,,,,,,,, diff --git a/Data/Resources/Metatable/Shaders.csv b/Data/Resources/Metatable/Shaders.csv new file mode 100644 index 0000000..c0d2337 --- /dev/null +++ b/Data/Resources/Metatable/Shaders.csv @@ -0,0 +1,2 @@ +name,path, +UI,UI.glsl, diff --git a/Data/Scripts/EditorApplication.lua b/Data/Scripts/EditorApplication.lua index d9f8b1f..8b54e41 100644 --- a/Data/Scripts/EditorApplication.lua +++ b/Data/Scripts/EditorApplication.lua @@ -63,6 +63,12 @@ GameLab.IO.ReadFilesAsync(files, function() Debug.Log("finished") end) +local imgData = Rendering.LoadImage("./Resources/Images/brickwall.jpg") +Debug.Log(tostring(imgData:GetWidth())) +Debug.Log(tostring(imgData:GetHeight())) + +local tex = Rendering.Texture.New(imgData, false) + while true do app:OnStep() diff --git a/Data/Scripts/EditorGUI/EditorImages.lua b/Data/Scripts/EditorGUI/EditorImages.lua index e98d064..3945edc 100644 --- a/Data/Scripts/EditorGUI/EditorImages.lua +++ b/Data/Scripts/EditorGUI/EditorImages.lua @@ -1,2 +1,25 @@ --- 编辑器图片资源 +-- 编辑器图片资源管理 +local EditorImages = {} +EditorImages.icons = {} --[name] = image, +EditorImages.gizmos = {} + +EditorImages.isImagesReady = false + +EditorImages.GetIcon = function(name) + +end + +EditorImages.GetGizmos = function(name) + +end + +local icons_metatable = "./Resources/Metatable/Icons.csv" +local gizmos_metatable = "./Resources/Metatable/Gizmos.csv" + +-- 读取所有的编辑器图片资源 +EditorImages.LoadAllImages = function() + +end + +return EditorImages \ No newline at end of file diff --git a/Data/boot.lua b/Data/boot.lua index 6f49da7..7e7cfdc 100644 --- a/Data/boot.lua +++ b/Data/boot.lua @@ -13,7 +13,8 @@ local editorCLibs = "./Libraries/?.dll" .. "./Plugins/?.dll" package.cpath=package.cpath .. ";" .. engineCLibs .. ";" .. editorCLibs -- debugging -require("LuaPanda").start("127.0.0.1",8818) +-- 在这里会报一个异常, 不知道为什么 +--require("LuaPanda").start("127.0.0.1",8818) -- redirect if GAMELAB_DEBUG then @@ -29,5 +30,8 @@ require "GameLab.Engine.GL" require "GameLab.Editor" require "GameLab.Editor.GUI" +-- debugging +require("LuaPanda").start("127.0.0.1",8818) + -- launch editor -dofile("./Scripts/EditorApplication.lua") \ No newline at end of file +dofile("./Scripts/EditorApplication.lua") diff --git a/Projects/VisualStudio/Editor/Editor.vcxproj b/Projects/VisualStudio/Editor/Editor.vcxproj index 39a9cf0..ad75401 100644 --- a/Projects/VisualStudio/Editor/Editor.vcxproj +++ b/Projects/VisualStudio/Editor/Editor.vcxproj @@ -209,8 +209,10 @@ + + diff --git a/Projects/VisualStudio/Editor/Editor.vcxproj.filters b/Projects/VisualStudio/Editor/Editor.vcxproj.filters index 29505ea..4170c69 100644 --- a/Projects/VisualStudio/Editor/Editor.vcxproj.filters +++ b/Projects/VisualStudio/Editor/Editor.vcxproj.filters @@ -336,6 +336,12 @@ Runtime\Scripting\Common + + Runtime\Scripting\Rendering + + + Runtime\Scripting\Rendering + diff --git a/Runtime/Debug/Log.cpp b/Runtime/Debug/Log.cpp index 4d28502..c92bdc8 100644 --- a/Runtime/Debug/Log.cpp +++ b/Runtime/Debug/Log.cpp @@ -63,9 +63,9 @@ void log_warning(std::string log) s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); } SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); - cout << currentDateTime() << " [Info] " << log << endl; + cout << currentDateTime() << " [Warning] " << log << endl; #else - cout << "\x1B[93m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl; + cout << "\x1B[93m" << currentDateTime() << " [Warning] " << log << "\x1B[0m" << endl; #endif } } @@ -78,9 +78,9 @@ void log_error(std::string log) s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); } SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_INTENSITY); - cout << currentDateTime() << " [Info] " << log << endl; + cout << currentDateTime() << " [Error] " << log << endl; #else - cout << "\x1B[91m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl; + cout << "\x1B[91m" << currentDateTime() << " [Error] " << log << "\x1B[0m" << endl; #endif } } diff --git a/Runtime/FileSystem/FileJobs.h b/Runtime/FileSystem/FileJobs.h index 50e681d..1fe49f1 100644 --- a/Runtime/FileSystem/FileJobs.h +++ b/Runtime/FileSystem/FileJobs.h @@ -18,7 +18,8 @@ public: void Process() override; bool IsFinished() override; + int cur = 0; //ǰļ std::vector files; // ļ· LuaBind::StrongRef callback; // ɺĻص -}; +}; \ No newline at end of file diff --git a/Runtime/Graphics/Device.h b/Runtime/Graphics/Device.h index e445efa..c7a059e 100644 --- a/Runtime/Graphics/Device.h +++ b/Runtime/Graphics/Device.h @@ -12,8 +12,8 @@ struct DeviceSetting { - TextureFilter texFilter; - TextureWrap texWrap; + ETextureFilterMode texFilter; + ETextureWrapMode texWrap; }; class Device : public NonCopyable @@ -46,8 +46,8 @@ public: GET_SET(Color, ClearColor, m_ClearColor); - GET_SET(TextureFilter, TextureFilter, m_TexFilter); - GET_SET(TextureWrap, TextureWrap, m_TexWrap); + GET_SET(ETextureFilterMode, TextureFilter, m_TexFilter); + GET_SET(ETextureWrapMode, TextureWrap, m_TexWrap); inline bool IsInsideFrame(); @@ -55,8 +55,8 @@ private: uint m_EnableFlag; // Global texture setting - TextureFilter m_TexFilter; - TextureWrap m_TexWrap; + ETextureFilterMode m_TexFilter; + ETextureWrapMode m_TexWrap; Color m_ClearColor; diff --git a/Runtime/Graphics/ImageData.h b/Runtime/Graphics/ImageData.h index af44f11..4663e0e 100644 --- a/Runtime/Graphics/ImageData.h +++ b/Runtime/Graphics/ImageData.h @@ -3,27 +3,54 @@ #include #include "Runtime/Threading/Job.h" +#include "Runtime/Lua/LuaHelper.h" // ͼƬ -class ImageData +class ImageData : public LuaBind::NativeClass { public: - enum ImageFormat + enum EPixelFormat { - ImageFormat_Rgba_Int, - ImageFormat_Rgba_Float, + RGBA, + RGB, + R, + RG, + BGR, + BGRA }; -private: - void* m_Data; + enum EPixelElementType + { + UNSIGNED_BYTE, + UNSIGNED_INT, + BYTE, + INT, + FLOAT, + }; + ImageData(LuaBind::VM* vm) + : LuaBind::NativeClass(vm) + { + } + + void* pixels; // ݣʽͲο http://docs.gl/gl3/glTexImage2D pixel dataformattype + EPixelFormat format; + EPixelElementType type; + int width, height; + +private: + LUA_BIND_DECL_CLASS(ImageData); + + LUA_BIND_DECL_METHOD(_GetWidth); + LUA_BIND_DECL_METHOD(_GetHeight); + LUA_BIND_DECL_METHOD(_GetSize); }; -enum ImageDataAsyncError +enum EImageDataAsyncError { - ImageDataAsyncError_NoFile = 1, - ImageDataAsyncError_ParseFailed = 2, - ImageDataAsyncError_InvalidFormat = 3, + NoFile = 1, + ParseFailed = 2, + InvalidFormat = 3, }; struct ImageDataRequest @@ -42,6 +69,8 @@ namespace ImageDataUtil ImageDataRequest* LoadAsync(std::vector paths); } +// ڹֻ߳ߵȡ->꣬ύGPU߳ + class ReadImageFilesJob : public Job { diff --git a/Runtime/Graphics/RenderTexture.h b/Runtime/Graphics/RenderTexture.h index 74c5602..a501f50 100644 --- a/Runtime/Graphics/RenderTexture.h +++ b/Runtime/Graphics/RenderTexture.h @@ -7,10 +7,10 @@ class RenderTexture : public Texture { public: - RenderTexture(TextureFormat format); + RenderTexture(ETextureFormat format); }; -RenderTexture* CreateRenderTexture(int width, int height, TextureFormat format); +RenderTexture* CreateRenderTexture(int width, int height, ETextureFormat format); #endif \ No newline at end of file diff --git a/Runtime/Graphics/Texture.cpp b/Runtime/Graphics/Texture.cpp index e69de29..ce09927 100644 --- a/Runtime/Graphics/Texture.cpp +++ b/Runtime/Graphics/Texture.cpp @@ -0,0 +1,69 @@ +#include "ImageData.h" +#include "Texture.h" + +using namespace LuaBind; + +Texture::Texture(LuaBind::VM* vm, TextureSetting setting, ImageData* imgData) + : NativeClass(vm) +{ + m_Width = imgData->width; + m_Height = imgData->height; + m_Type = setting.type; + m_Format = setting.format; + m_WrapMode = setting.wrapMode; + m_FilterMode = setting.filterMode; + m_KeepPixelData = setting.keepImageData; + + glGenTextures(1, &m_GPUID); + glBindTexture(GL_TEXTURE_2D, m_GPUID); + + switch (m_WrapMode) { + case ETextureWrapMode::Clamp: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + break; + case ETextureWrapMode::Repeat: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + break; + case ETextureWrapMode::Mirror: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + break; + default: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + break; + } + + switch (m_FilterMode) { + case ETextureFilterMode::Linear: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + case ETextureFilterMode::Nearest: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + default: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imgData->width, imgData->height, 0, GL_RGB, GL_UNSIGNED_BYTE, imgData->pixels); + + // keep image data ? + if (m_KeepPixelData) + { + LuaBind::State state = vm->GetCurThread(); + imgData->PushUserdata(state); + SetMemberRef(state, m_ImageData, -1); + state.Pop(1); + } +} + +Texture::~Texture() +{ + glDeleteTextures(1, &m_GPUID); +} \ No newline at end of file diff --git a/Runtime/Graphics/Texture.h b/Runtime/Graphics/Texture.h index d09429c..30cf303 100644 --- a/Runtime/Graphics/Texture.h +++ b/Runtime/Graphics/Texture.h @@ -1,61 +1,96 @@ -#ifndef TEXTURE_H -#define TEXTURE_H +#pragma once +#include #include "Runtime/Lua/LuaHelper.h" -#include "Runtime/Lua/LuaBind/LuaBind.h" #include "../Utilities/UtilMacros.h" #include "OpenGL.h" -#include "ImageData.h" -enum TextureFormat +class ImageData; + +enum ETextureType +{ + TEX_2D, + TEX_CUBE, +}; + +enum ETextureFormat +{ + RGBA32, + RGB24, + RGB16, + R8, + A8, +}; + +enum ETextureWrapMode +{ + Clamp, + Repeat, + Mirror, +}; + +enum ETextureFilterMode { - TextureFormat_DepthComponent, - TextureFormat_Red, - TextureFormat_Green, - TextureFormat_Blue, - TextureFormat_Alpha, - TextureFormat_Rgb, - TextureFormat_Rgba, + Nearest, + Linear, }; -enum TextureWrap +struct TextureSetting { - TextureWrap_Clamp, - TextureWrap_Repeat, + bool keepImageData; // Ƿ񱣴ͼƬ + int type; // ͼƬ + int format; // ڲʽ + int wrapMode; // Χ + int filterMode; // ˲ }; -enum TextureFilter +class TextureException : public std::exception { - TextureFilter_Nearest, - TextureFilter_Bilinear, - TextureFilter_Trilinear, +public: + TextureException(const char* what) + : std::exception(what) + {} }; -class Texture +class Texture : public LuaBind::NativeClass { public: - Texture(); - Texture(ImageData* imgData, TextureFormat format); - Texture(ImageData* imgData, TextureFormat format, TextureWrap wrap, TextureFilter filter); + Texture(LuaBind::VM* vm, TextureSetting setting, ImageData* imgData)/*throw TextureException*/; ~Texture(); GET(int, Width, m_Width); GET(int, Height, m_Height); - GET(TextureFilter, Filter, m_Filter); - GET(TextureWrap, Wrap, m_Wrap); - - GET(GLint, Handle, m_Handle); + GET(GLuint, GpuID, m_GPUID); protected: - GLint m_Handle; + GLuint m_GPUID; + int m_Width, m_Height; - TextureFilter m_Filter; - TextureWrap m_Wrap; -}; + int m_Type; + int m_Format; + int m_FilterMode; + int m_WrapMode; + + bool m_KeepPixelData; // Ƿ񱣴ͼݣĬϵ󲻱 + + LuaBind::MemberRef m_ImageData; //ͼƬ + + LUA_BIND_DECL_CLASS(Texture); + + LUA_BIND_DECL_METHOD(_New); + + LUA_BIND_DECL_METHOD(_GetWidth); + LUA_BIND_DECL_METHOD(_GetHeight); + LUA_BIND_DECL_METHOD(_GetSize); + + LUA_BIND_DECL_METHOD(_GetType); + LUA_BIND_DECL_METHOD(_GetFormat); + LUA_BIND_DECL_METHOD(_GetWrapMode); + LUA_BIND_DECL_METHOD(_GetFilterMode); -Texture* CreateTexture(ImageData* imgData, TextureFormat format); -Texture* CreateTexture(ImageData* imgData, TextureFormat format, TextureWrap wrap, TextureFilter filter); + LUA_BIND_DECL_METHOD(_IsKeepImageData); + LUA_BIND_DECL_METHOD(_GetImageData); -#endif \ No newline at end of file +}; \ No newline at end of file diff --git a/Runtime/Lua/LuaHelper.cpp b/Runtime/Lua/LuaHelper.cpp index 2044ba2..9381b6c 100644 --- a/Runtime/Lua/LuaHelper.cpp +++ b/Runtime/Lua/LuaHelper.cpp @@ -59,4 +59,9 @@ bool LuaHelper::IsType(LuaBind::State& state, const char* typeName, int idx) bool bIsType = tname == typeName; state.SetTop(top); return bIsType; +} + +bool LuaHelper::InstantiateClass(LuaBind::State& state, const char* classFullName) +{ + return false; } \ No newline at end of file diff --git a/Runtime/Lua/LuaHelper.h b/Runtime/Lua/LuaHelper.h index 56dae54..c3cd70e 100644 --- a/Runtime/Lua/LuaHelper.h +++ b/Runtime/Lua/LuaHelper.h @@ -5,13 +5,14 @@ // lua 5.1 doc: https://www.lua.org/manual/5.1/ +// GameLabһЩչ class LuaHelper { public: static int Call(const char* func, const char* params, ...); - static bool IsType(LuaBind::State& state, const char* typeName, int idx); - static void OnRegisterNativeClass(LuaBind::State& state, int cls, std::string clsName, std::string pkgName); - + // luaʵջʧܷfalseҲѹջ + static bool InstantiateClass(LuaBind::State& state, const char* classFullName); + }; \ No newline at end of file diff --git a/Runtime/Scripting/Rendering/ImageData.bind.cpp b/Runtime/Scripting/Rendering/ImageData.bind.cpp new file mode 100644 index 0000000..88412e5 --- /dev/null +++ b/Runtime/Scripting/Rendering/ImageData.bind.cpp @@ -0,0 +1,38 @@ +#include "Runtime/Graphics/ImageData.h" + +using namespace LuaBind; + +LUA_BIND_REGISTRY(ImageData) +{ + LUA_BIND_REGISTER_METHODS(state, + { "GetWidth", _GetWidth }, + { "GetHeight", _GetHeight }, + { "GetSize", _GetSize } + ); +} + +LUA_BIND_POSTPROCESS(ImageData) +{ +} + +LUA_BIND_IMPL_METHOD(ImageData, _GetWidth) +{ + LUA_BIND_PREPARE(L, ImageData); + state.Push(self->width); + return 1; +} + +LUA_BIND_IMPL_METHOD(ImageData, _GetHeight) +{ + LUA_BIND_PREPARE(L, ImageData); + state.Push(self->height); + return 1; +} + +LUA_BIND_IMPL_METHOD(ImageData, _GetSize) +{ + LUA_BIND_PREPARE(L, ImageData); + state.Push(self->width); + state.Push(self->height); + return 2; +} diff --git a/Runtime/Scripting/Rendering/Rendering.bind.cpp b/Runtime/Scripting/Rendering/Rendering.bind.cpp index 29fa421..40b3ac5 100644 --- a/Runtime/Scripting/Rendering/Rendering.bind.cpp +++ b/Runtime/Scripting/Rendering/Rendering.bind.cpp @@ -1,4 +1,32 @@ #include "Runtime/Graphics/Shader.h" +#include "Runtime/Graphics/Texture.h" +#include "Runtime/Graphics/ImageData.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "ThirdParty/stb/stb_image.h" + +// imgData = Rendering.LoadImage(path) +int LoadImage(lua_State* L) +{ + LUA_BIND_STATE(L); + + const char* path = state.GetValue(1, ""); + + stbi_set_flip_vertically_on_load(true); + ImageData* data = new ImageData(state.GetVM()); + int channels; + data->pixels = stbi_load(path, &data->width, &data->height, &channels, 0); + data->format = ImageData::EPixelFormat::RGB; + data->type = ImageData::EPixelElementType::UNSIGNED_BYTE; + + data->PushUserdata(state); + return 1; +} + +static luaL_Reg funcs[] = { + {"LoadImage", LoadImage}, + {0, 0} +}; int luaopen_GameLab_Engine_Rendering(lua_State* L) { @@ -11,7 +39,11 @@ int luaopen_GameLab_Engine_Rendering(lua_State* L) state.PushNamespace("Engine"); state.PushNamespace("Rendering"); + state.RegisterMethods(funcs); + state.RegisterNativeClass(); + state.RegisterNativeClass(); + state.RegisterNativeClass(); return 1; } \ No newline at end of file diff --git a/Runtime/Scripting/Rendering/Texture.bind.cpp b/Runtime/Scripting/Rendering/Texture.bind.cpp new file mode 100644 index 0000000..061a303 --- /dev/null +++ b/Runtime/Scripting/Rendering/Texture.bind.cpp @@ -0,0 +1,143 @@ +#include "Runtime/Graphics/Texture.h" + +using namespace LuaBind; + +LUA_BIND_REGISTRY(Texture) +{ + LUA_BIND_REGISTER_METHODS(state, + { "New", _New }, + { "GetWidth", _GetWidth }, + { "GetHeight", _GetHeight }, + { "GetSize", _GetSize }, + { "GetType", _GetType }, + { "GetFormat", _GetFormat }, + { "GetWrapMode", _GetWrapMode }, + { "GetImageData", _GetImageData }, + { "IsKeepImageData", _IsKeepImageData }, + { "GetFilterMode", _GetFilterMode } + ); +} + +LUA_BIND_POSTPROCESS(Texture) +{ + LUA_BIND_REGISTER_ENUM(state, "ETextureType", + { "TEX_2D", ETextureType::TEX_2D }, + { "TEX_CUBE", ETextureType::TEX_CUBE } + ); + LUA_BIND_REGISTER_ENUM(state, "ETextureFormat", + { "RGBA32", ETextureFormat::RGBA32 }, + { "RGB24", ETextureFormat::RGB24 }, + { "RGB16", ETextureFormat::RGB16 }, + { "R8", ETextureFormat::R8 }, + { "A8", ETextureFormat::A8 } + ); + LUA_BIND_REGISTER_ENUM(state, "ETextureWrapMode", + { "Clamp", ETextureWrapMode::Clamp }, + { "Repeat", ETextureWrapMode::Repeat }, + { "Mirror", ETextureWrapMode::Mirror } + ); + LUA_BIND_REGISTER_ENUM(state, "ETextureFilterMode", + { "Nearest", ETextureFilterMode::Nearest }, + { "Linear", ETextureFilterMode::Linear } + ); +} + +// Texture.New(imgData, keepImgData, type, format, wrapMode, filterMode) +LUA_BIND_IMPL_METHOD(Texture, _New) +{ + LUA_BIND_STATE(L); + LUA_BIND_CHECK(L, "U"); + + ImageData* imgData = state.GetUserdata(1); + + TextureSetting setting; + setting.keepImageData = state.GetValue(2, false); + setting.type = state.GetValue(3, (int)ETextureType::TEX_2D); + setting.format = state.GetValue(4, (int)ETextureFormat::RGBA32); + setting.wrapMode = state.GetValue(5, (int)ETextureWrapMode::Clamp); + setting.filterMode = state.GetValue(6, (int)ETextureFilterMode::Linear); + + try + { + Texture* tex = new Texture(state.GetVM(), setting, imgData); + tex->PushUserdata(state); + return 1; + } + catch (TextureException e) + { + luaL_error(L, "Failed to create texture."); + return 0; + } + return 0; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetWidth) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Width); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetHeight) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Height); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetSize) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Width); + state.Push(self->m_Height); + return 2; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetType) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Type); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetFormat) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Format); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetWrapMode) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_WrapMode); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetFilterMode) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_FilterMode); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _IsKeepImageData) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_KeepPixelData); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetImageData) +{ + LUA_BIND_PREPARE(L, Texture); + if (self->m_KeepPixelData) + { + self->PushMemberRef(state, self->m_ImageData); + } + else + { + state.PushNil(); + } + return 1; +} -- cgit v1.1-26-g67d0