Merge pull request #192 from MihailRis/worldwide-refactor
Worldwide refactor: in search of good architecture
@@ -8,6 +8,7 @@ Debug/voxel_engine
|
|||||||
/screenshots
|
/screenshots
|
||||||
/out
|
/out
|
||||||
|
|
||||||
|
/misc
|
||||||
/world
|
/world
|
||||||
/worlds/**/*
|
/worlds/**/*
|
||||||
/settings.toml
|
/settings.toml
|
||||||
@@ -41,4 +42,4 @@ appimage-build/
|
|||||||
*~
|
*~
|
||||||
|
|
||||||
/res/content/*
|
/res/content/*
|
||||||
!/res/content/base
|
!/res/content/base
|
||||||
|
|||||||
@@ -95,6 +95,26 @@ world.get_seed() -> int
|
|||||||
|
|
||||||
Returns world seed.
|
Returns world seed.
|
||||||
|
|
||||||
|
## *pack* library
|
||||||
|
|
||||||
|
```python
|
||||||
|
pack.get_folder(packid: str) -> str
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns installed content-pack folder
|
||||||
|
|
||||||
|
```python
|
||||||
|
pack.is_installed(packid: str) -> bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Check if the world has specified pack installed
|
||||||
|
|
||||||
|
```python
|
||||||
|
pack.get_installed() -> array of strings
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all installed content-pack ids
|
||||||
|
|
||||||
## *gui* library
|
## *gui* library
|
||||||
|
|
||||||
Library contains ui elements access functions. Library should not be directly used, because script *layouts/layout_name.xml.lua* already has a generated variable **document** (instance of **Document**)
|
Library contains ui elements access functions. Library should not be directly used, because script *layouts/layout_name.xml.lua* already has a generated variable **document** (instance of **Document**)
|
||||||
@@ -161,6 +181,13 @@ inventory.clone(invid: int) -> int
|
|||||||
|
|
||||||
Create inventory copy. Returns the created copy ID.
|
Create inventory copy. Returns the created copy ID.
|
||||||
|
|
||||||
|
```python
|
||||||
|
inventory.move(invA: int, slotA: int, invB: int, slotB: int)
|
||||||
|
```
|
||||||
|
|
||||||
|
Move item from slotA of invA to slotB of invB. invA may be the same as invB.
|
||||||
|
If slotB will be chosen automaticly if argument is not specified.
|
||||||
|
|
||||||
## *block* library
|
## *block* library
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -337,6 +364,13 @@ hud.close(layoutid: str)
|
|||||||
|
|
||||||
Remove an element from the screen
|
Remove an element from the screen
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
hud.get_block_inventory() -> int
|
||||||
|
```
|
||||||
|
|
||||||
|
Get open block inventory ID or 0
|
||||||
|
|
||||||
## Block events
|
## Block events
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
|||||||
@@ -89,6 +89,26 @@ world.get_seed() -> int
|
|||||||
|
|
||||||
Возвращает зерно мира.
|
Возвращает зерно мира.
|
||||||
|
|
||||||
|
## Библиотека pack
|
||||||
|
|
||||||
|
```python
|
||||||
|
pack.get_folder(packid: str) -> str
|
||||||
|
```
|
||||||
|
|
||||||
|
Возвращает путь к папке установленного контент-пака
|
||||||
|
|
||||||
|
```python
|
||||||
|
pack.is_installed(packid: str) -> bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверяет наличие контент-пака в мире
|
||||||
|
|
||||||
|
```python
|
||||||
|
pack.get_installed() -> массив строк
|
||||||
|
```
|
||||||
|
|
||||||
|
Возращает id всех установленных в мире контент-паков
|
||||||
|
|
||||||
## Библиотека gui
|
## Библиотека gui
|
||||||
|
|
||||||
Библиотека содержит функции для доступа к свойствам UI элементов. Вместо gui следует использовать объектную обертку, предоставляющую доступ к свойствам через мета-методы __index, __newindex:
|
Библиотека содержит функции для доступа к свойствам UI элементов. Вместо gui следует использовать объектную обертку, предоставляющую доступ к свойствам через мета-методы __index, __newindex:
|
||||||
@@ -155,6 +175,14 @@ inventory.clone(invid: int) -> int
|
|||||||
|
|
||||||
Создает копию инвентаря и возвращает id копии. Если копируемого инвентаря не существует, возвращает 0.
|
Создает копию инвентаря и возвращает id копии. Если копируемого инвентаря не существует, возвращает 0.
|
||||||
|
|
||||||
|
```python
|
||||||
|
inventory.move(invA: int, slotA: int, invB: int, slotB: int)
|
||||||
|
```
|
||||||
|
|
||||||
|
Перемещает предмет из slotA инвентаря invA в slotB инвентаря invB.
|
||||||
|
invA и invB могут указывать на один инвентарь.
|
||||||
|
slotB будет выбран автоматически, если не указывать явно.
|
||||||
|
|
||||||
## Библиотека block
|
## Библиотека block
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -326,6 +354,13 @@ hud.close(layoutid: str)
|
|||||||
```
|
```
|
||||||
|
|
||||||
Удаляет элемент с экрана
|
Удаляет элемент с экрана
|
||||||
|
|
||||||
|
```python
|
||||||
|
hud.get_block_inventory() -> int
|
||||||
|
```
|
||||||
|
|
||||||
|
Получить ID инвентаря открытого блока или 0
|
||||||
|
|
||||||
## События блоков
|
## События блоков
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
bazalt=Bazalt
|
|
||||||
blue_lamp=Blue Lamp
|
|
||||||
brick=Brick
|
|
||||||
dirt=Dirt
|
|
||||||
flower=Flower
|
|
||||||
glass=Glass
|
|
||||||
grass_block=Ground
|
|
||||||
grass=Tall Grass
|
|
||||||
green_lamp=Green Lamp
|
|
||||||
lamp=Lamp
|
|
||||||
leaves=Leaves
|
|
||||||
lightbulb=Bulb
|
|
||||||
metal=Metal
|
|
||||||
pane=Pane
|
|
||||||
pipe=Pipe
|
|
||||||
planks=Planks
|
|
||||||
red_lamp=Red Lamp
|
|
||||||
rust=Rust
|
|
||||||
sand=Sand
|
|
||||||
stone=Stone
|
|
||||||
water=Water
|
|
||||||
wood=Wood
|
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
bazalt=Базальт
|
bazalt=базальт
|
||||||
blue_lamp=Синяя Лампа
|
blue lamp=синяя лампа
|
||||||
brick=Кирпич
|
brick=кирпич
|
||||||
dirt=Земля
|
dirt=земля
|
||||||
flower=Цветок
|
flower=цветок
|
||||||
glass=Стекло
|
glass=стекло
|
||||||
grass_block=Дёрн
|
grass block=дёрн
|
||||||
grass=Высокая Трава
|
tall grass=высокая трава
|
||||||
green_lamp=Зелёная Лампа
|
green lamp=зелёная лампа
|
||||||
lamp=Лампа
|
lamp=лампа
|
||||||
leaves=Листва
|
leaves=листва
|
||||||
lightbulb=Лампочка
|
light bulb=лампочка
|
||||||
metal=Металл
|
metal=металл
|
||||||
pane=Панель
|
pane=панель
|
||||||
pipe=Труба
|
pipe=труба
|
||||||
planks=Доски
|
planks=доски
|
||||||
red_lamp=Красная Лампа
|
red lamp=красная лампа
|
||||||
rust=Ржавчина
|
rust=ржавчина
|
||||||
sand=Песок
|
sand=песок
|
||||||
stone=Камень
|
stone=камень
|
||||||
water=Вода
|
water=вода
|
||||||
wood=Бревно
|
wood=бревно
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
function inventory_share_func(invid, slotid)
|
function inventory_share_func(invid, slotid)
|
||||||
inventory.set(invid, slotid, 0, 0)
|
local blockinv = hud.get_block_inventory()
|
||||||
|
if blockinv ~= 0 then
|
||||||
|
inventory.move(invid, slotid, blockinv)
|
||||||
|
else
|
||||||
|
inventory.set(invid, slotid, 0, 0)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<panel size='400' padding='8' interval='8' color='0'>
|
||||||
|
<label context='menu'>@Page not found</label>
|
||||||
|
<button onclick='menu:back()'>@Back</button>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<container size='887,454' color='#0F1E2DB2' padding='8' interval='5' context='menu'>
|
||||||
|
<panel id='packs_cur' pos='2' size='440,406' color='0' max-length='406'>
|
||||||
|
<!-- content is generated in script -->
|
||||||
|
</panel>
|
||||||
|
<panel id='packs_add' pos='445,2' size='440,406' color='0' max-length='406'>
|
||||||
|
<!-- content is generated in script -->
|
||||||
|
</panel>
|
||||||
|
<button id='apply_btn' pos='2,410' size='440,40' onclick='apply()'>@Apply</button>
|
||||||
|
<button pos='445,410' size='398,40' onclick='menu:back()'>@Cancel</button>
|
||||||
|
<image onclick='refresh()' interactive='true' src='gui/refresh'
|
||||||
|
size='32' margin='7' gravity='bottom-right'
|
||||||
|
color='#FFFFFF80' hover-color='#FFFFFF10'/>
|
||||||
|
</container>
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
function on_open(params)
|
||||||
|
if params then
|
||||||
|
mode = params.mode
|
||||||
|
end
|
||||||
|
refresh()
|
||||||
|
end
|
||||||
|
|
||||||
|
add_packs = {}
|
||||||
|
rem_packs = {}
|
||||||
|
|
||||||
|
function apply()
|
||||||
|
core.reconfig_packs(add_packs, rem_packs)
|
||||||
|
if mode ~= "world" then
|
||||||
|
menu:back()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function refresh_changes()
|
||||||
|
document.apply_btn.enabled = (#add_packs>0) or (#rem_packs>0)
|
||||||
|
end
|
||||||
|
|
||||||
|
function move_pack(id)
|
||||||
|
-- cancel pack addition
|
||||||
|
if table.has(add_packs, id) then
|
||||||
|
document["pack_"..id]:move_into(document.packs_add)
|
||||||
|
table.remove_value(add_packs, id)
|
||||||
|
-- cancel pack removal
|
||||||
|
elseif table.has(rem_packs, id) then
|
||||||
|
document["pack_"..id]:move_into(document.packs_cur)
|
||||||
|
table.remove_value(rem_packs, id)
|
||||||
|
-- add pack
|
||||||
|
elseif table.has(packs_installed, id) then
|
||||||
|
document["pack_"..id]:move_into(document.packs_add)
|
||||||
|
table.insert(rem_packs, id)
|
||||||
|
-- remove pack
|
||||||
|
else
|
||||||
|
document["pack_"..id]:move_into(document.packs_cur)
|
||||||
|
table.insert(add_packs, id)
|
||||||
|
end
|
||||||
|
refresh_changes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function place_pack(panel, packinfo, callback)
|
||||||
|
if packinfo.error then
|
||||||
|
callback = nil
|
||||||
|
end
|
||||||
|
if packinfo.has_indices then
|
||||||
|
packinfo.id_verbose = packinfo.id.."*"
|
||||||
|
else
|
||||||
|
packinfo.id_verbose = packinfo.id
|
||||||
|
end
|
||||||
|
packinfo.callback = callback
|
||||||
|
panel:add(gui.template("pack", packinfo))
|
||||||
|
if not callback then
|
||||||
|
document["pack_"..packinfo.id].enabled = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function check_dependencies(packinfo)
|
||||||
|
if packinfo.dependencies == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for i,dep in ipairs(packinfo.dependencies) do
|
||||||
|
local depid = dep:sub(2,-1)
|
||||||
|
if dep:sub(1,1) == '!' then
|
||||||
|
if not table.has(packs_all, depid) then
|
||||||
|
return string.format(
|
||||||
|
"%s (%s)", gui.str("error.dependency-not-found"), depid
|
||||||
|
)
|
||||||
|
end
|
||||||
|
if table.has(packs_installed, packinfo.id) then
|
||||||
|
table.insert(required, depid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
function refresh()
|
||||||
|
packs_installed = pack.get_installed()
|
||||||
|
packs_available = pack.get_available()
|
||||||
|
base_packs = pack.get_base_packs()
|
||||||
|
packs_all = {unpack(packs_installed)}
|
||||||
|
required = {}
|
||||||
|
for i,k in ipairs(packs_available) do
|
||||||
|
table.insert(packs_all, k)
|
||||||
|
end
|
||||||
|
|
||||||
|
local packs_cur = document.packs_cur
|
||||||
|
local packs_add = document.packs_add
|
||||||
|
packs_cur:clear()
|
||||||
|
packs_add:clear()
|
||||||
|
|
||||||
|
for i,id in ipairs(packs_installed) do
|
||||||
|
local packinfo = pack.get_info(id)
|
||||||
|
packinfo.index = i
|
||||||
|
callback = not table.has(base_packs, id) and string.format('move_pack("%s")', id) or nil
|
||||||
|
packinfo.error = check_dependencies(packinfo)
|
||||||
|
place_pack(packs_cur, packinfo, callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
for i,id in ipairs(packs_available) do
|
||||||
|
local packinfo = pack.get_info(id)
|
||||||
|
packinfo.index = i
|
||||||
|
callback = string.format('move_pack("%s")', id)
|
||||||
|
packinfo.error = check_dependencies(packinfo)
|
||||||
|
place_pack(packs_add, packinfo, callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
for i,id in ipairs(packs_installed) do
|
||||||
|
if table.has(required, id) then
|
||||||
|
document["pack_"..id].enabled = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
apply_movements(packs_cur, packs_add)
|
||||||
|
refresh_changes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function apply_movements(packs_cur, packs_add)
|
||||||
|
for i,id in ipairs(packs_installed) do
|
||||||
|
if table.has(rem_packs, id) then
|
||||||
|
document["pack_"..id]:move_into(packs_add)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i,id in ipairs(packs_available) do
|
||||||
|
if table.has(add_packs, id) then
|
||||||
|
document["pack_"..id]:move_into(packs_cur)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<panel size='400' color='#00000080' padding='8' context='settings'>
|
||||||
|
<!-- content is generated in script -->
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
settings = session.get_entry('new_world')
|
||||||
|
|
||||||
|
function on_open()
|
||||||
|
local names = core.get_generators()
|
||||||
|
table.sort(names)
|
||||||
|
|
||||||
|
local panel = document.root
|
||||||
|
for _,k in ipairs(names) do
|
||||||
|
panel:add(gui.template("generator", {
|
||||||
|
callback=string.format("settings.generator=%q menu:back()", k),
|
||||||
|
id=k,
|
||||||
|
name=settings.generator_name(k)
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
panel:add("<button onclick='menu:back()'>@Back</button>")
|
||||||
|
end
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<panel size='400' color='#00000080' padding='8'>
|
||||||
|
<!-- content is generated in script -->
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
function on_open()
|
||||||
|
local locales = gui.get_locales_info()
|
||||||
|
local invlocales = {}
|
||||||
|
local names = {}
|
||||||
|
for k, v in pairs(locales) do
|
||||||
|
table.insert(names, v.name)
|
||||||
|
invlocales[v.name] = k
|
||||||
|
end
|
||||||
|
table.sort(names)
|
||||||
|
|
||||||
|
local panel = document.root
|
||||||
|
for _,k in ipairs(names) do
|
||||||
|
panel:add(string.format(
|
||||||
|
"<button onclick=%q>%s</button>",
|
||||||
|
string.format("core.set_setting('ui.language', %q) menu:back()", invlocales[k]), k
|
||||||
|
))
|
||||||
|
end
|
||||||
|
panel:add("<button onclick='menu:back()'>@Back</button>")
|
||||||
|
end
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<panel size='400' color='0' interval='1' context='menu'>
|
||||||
|
<button onclick='menu.page="new_world"'>@New World</button>
|
||||||
|
<panel id='worlds' size='390,1' padding='5' color='#FFFFFF11' max-length='400'>
|
||||||
|
</panel>
|
||||||
|
<button onclick='menu.page="settings"'>@Settings</button>
|
||||||
|
<button onclick='core.quit()'>@Quit</button>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
function on_open()
|
||||||
|
local worlds = world.get_list()
|
||||||
|
for _, info in ipairs(worlds) do
|
||||||
|
document.worlds:add(gui.template("world", info))
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<panel size='400' color='0' interval='1' context='world'>
|
||||||
|
<label>@Name</label>
|
||||||
|
<textbox id='name_box'
|
||||||
|
validator='world_name_validator'
|
||||||
|
placeholder='New World'
|
||||||
|
padding='4'>
|
||||||
|
</textbox>
|
||||||
|
<label>@Seed</label>
|
||||||
|
<textbox id='seed_box' placeholder='-' padding='4'></textbox>
|
||||||
|
<button onclick='save_state() menu.page="generators"' id='generator_btn'>
|
||||||
|
@World generator
|
||||||
|
</button>
|
||||||
|
<button id='content_btn' onclick='save_state() menu.page="content"'/>
|
||||||
|
<button onclick='create_world()' margin='1,20,1,1'>
|
||||||
|
@Create World
|
||||||
|
</button>
|
||||||
|
<button onclick='menu:back()'>@Back</button>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
settings = session.get_entry('new_world')
|
||||||
|
|
||||||
|
function world_name_validator(name)
|
||||||
|
return name:match("^[%w-\\.\\ ]+$") ~= nil and not world.exists(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function save_state()
|
||||||
|
settings.name = document.name_box.text
|
||||||
|
settings.seed = document.seed_box.text
|
||||||
|
end
|
||||||
|
|
||||||
|
function settings.generator_name(id)
|
||||||
|
local prefix, name = parse_path(id)
|
||||||
|
if prefix == "core" then
|
||||||
|
return gui.str(name, "world.generators")
|
||||||
|
else
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function create_world()
|
||||||
|
if not document.name_box.valid then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = document.name_box.text
|
||||||
|
local seed = document.seed_box.text
|
||||||
|
local generator = settings.generator
|
||||||
|
session.reset_entry('new_world')
|
||||||
|
core.new_world(name, seed, generator)
|
||||||
|
end
|
||||||
|
|
||||||
|
function on_open()
|
||||||
|
document.content_btn.text = string.format(
|
||||||
|
"%s [%s]", gui.str("Content", "menu"), #pack.get_installed()
|
||||||
|
)
|
||||||
|
if settings.generator == nil then
|
||||||
|
settings.generator = core.get_default_generator()
|
||||||
|
end
|
||||||
|
document.generator_btn.text = string.format(
|
||||||
|
"%s: %s",
|
||||||
|
gui.str("World generator", "world"),
|
||||||
|
settings.generator_name(settings.generator)
|
||||||
|
)
|
||||||
|
document.name_box.text = settings.name or ''
|
||||||
|
document.seed_box.text = settings.seed or ''
|
||||||
|
document.seed_box.placeholder = tostring(math.random()):sub(3)
|
||||||
|
end
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<panel size='400' color='0' interval='1' context='menu'>
|
||||||
|
<button onclick='menu:reset()'>@Continue</button>
|
||||||
|
<button onclick='menu.page="content?mode=world"'>@Content</button>
|
||||||
|
<button onclick='menu.page="settings"'>@Settings</button>
|
||||||
|
<button onclick='core.close_world(true)'>
|
||||||
|
@Save and Quit to Menu
|
||||||
|
</button>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<container size='668,418' color='#0F1E2DB2' context='menu'>
|
||||||
|
<panel pos='6' size='250' color='0' interval='1'>
|
||||||
|
<button id='s_aud' onclick='set_page("s_aud", "settings_audio")'>@Audio</button>
|
||||||
|
<button id='s_gfx' onclick='set_page("s_gfx", "settings_graphics")'>@Graphics</button>
|
||||||
|
<button id='s_ctl' onclick='set_page("s_ctl", "settings_controls")'>@Controls</button>
|
||||||
|
</panel>
|
||||||
|
<pagebox id='menu' pos='260,6' size='400'>
|
||||||
|
</pagebox>
|
||||||
|
|
||||||
|
<panel margin='6' gravity='bottom-left' size='250' color='0' interval='1'>
|
||||||
|
<button onclick='menu.page="languages"' id='langs_btn'>-</button>
|
||||||
|
<button onclick='menu:back()'>@Back</button>
|
||||||
|
</panel>
|
||||||
|
</container>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
function on_open()
|
||||||
|
document.langs_btn.text = string.format(
|
||||||
|
"%s: %s", gui.str("Language", "settings"),
|
||||||
|
gui.get_locales_info()[core.get_setting("ui.language")].name
|
||||||
|
)
|
||||||
|
set_page("s_gfx", "settings_graphics")
|
||||||
|
end
|
||||||
|
|
||||||
|
function set_page(btn, page)
|
||||||
|
document.s_aud.enabled = true
|
||||||
|
document.s_gfx.enabled = true
|
||||||
|
document.s_ctl.enabled = true
|
||||||
|
document[btn].enabled = false
|
||||||
|
document.menu.page = page
|
||||||
|
end
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<panel size='400' color='0' interval='1'>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
function create_setting(id, name, step, postfix)
|
||||||
|
local info = core.get_setting_info(id)
|
||||||
|
postfix = postfix or ""
|
||||||
|
document.root:add(gui.template("track_setting", {
|
||||||
|
id=id,
|
||||||
|
name=gui.str(name, "settings"),
|
||||||
|
value=core.get_setting(id),
|
||||||
|
min=info.min,
|
||||||
|
max=info.max,
|
||||||
|
step=step,
|
||||||
|
postfix=postfix
|
||||||
|
}))
|
||||||
|
update_setting(core.get_setting(id), id, name, postfix)
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_setting(x, id, name, postfix)
|
||||||
|
core.set_setting(id, x)
|
||||||
|
-- updating label
|
||||||
|
document[id..".L"].text = string.format(
|
||||||
|
"%s: %s%s",
|
||||||
|
gui.str(name, "settings"),
|
||||||
|
core.str_setting(id),
|
||||||
|
postfix
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function on_open()
|
||||||
|
create_setting("audio.volume-master", "Master Volume", 0.01)
|
||||||
|
create_setting("audio.volume-regular", "Regular Sounds", 0.01)
|
||||||
|
create_setting("audio.volume-ui", "UI Sounds", 0.01)
|
||||||
|
create_setting("audio.volume-ambient", "Ambient", 0.01)
|
||||||
|
create_setting("audio.volume-music", "Music", 0.01)
|
||||||
|
end
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<panel size='400' color='0'>
|
||||||
|
<label id='sensitivity_label'>-</label>
|
||||||
|
<trackbar id='sensitivity_track'
|
||||||
|
min='0.1' max='10' value='2' step='0.1'
|
||||||
|
consumer='change_sensitivity'>
|
||||||
|
</trackbar>
|
||||||
|
<panel id='bindings_panel' size='380,204' padding='2' interval='1' max-length='350' color='#0000004C'>
|
||||||
|
<!-- content is generated in script -->
|
||||||
|
</panel>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
function refresh_sensitivity()
|
||||||
|
document.sensitivity_label.text = string.format(
|
||||||
|
"%s: %s",
|
||||||
|
gui.str("Mouse Sensitivity", "settings"),
|
||||||
|
core.str_setting("camera.sensitivity")
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function change_sensitivity(val)
|
||||||
|
core.set_setting("camera.sensitivity", val)
|
||||||
|
refresh_sensitivity()
|
||||||
|
end
|
||||||
|
|
||||||
|
function on_open()
|
||||||
|
document.sensitivity_track.value = core.get_setting("camera.sensitivity")
|
||||||
|
refresh_sensitivity()
|
||||||
|
|
||||||
|
local panel = document.bindings_panel
|
||||||
|
local bindings = core.get_bindings()
|
||||||
|
for i,name in ipairs(bindings) do
|
||||||
|
panel:add(gui.template("binding", {
|
||||||
|
id=name, name=gui.str(name)
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<panel size='400' color='0' interval='1' context='menu'>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
function create_setting(id, name, step, postfix)
|
||||||
|
local info = core.get_setting_info(id)
|
||||||
|
postfix = postfix or ""
|
||||||
|
document.root:add(gui.template("track_setting", {
|
||||||
|
id=id,
|
||||||
|
name=gui.str(name, "settings"),
|
||||||
|
value=core.get_setting(id),
|
||||||
|
min=info.min,
|
||||||
|
max=info.max,
|
||||||
|
step=step,
|
||||||
|
postfix=postfix
|
||||||
|
}))
|
||||||
|
update_setting(core.get_setting(id), id, name, postfix)
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_setting(x, id, name, postfix)
|
||||||
|
core.set_setting(id, x)
|
||||||
|
-- updating label
|
||||||
|
document[id..".L"].text = string.format(
|
||||||
|
"%s: %s%s",
|
||||||
|
gui.str(name, "settings"),
|
||||||
|
core.str_setting(id),
|
||||||
|
postfix
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function create_checkbox(id, name)
|
||||||
|
document.root:add(string.format(
|
||||||
|
"<checkbox consumer='function(x) core.set_setting(\"%s\", x) end' checked='%s'>%s</checkbox>",
|
||||||
|
id, core.str_setting(id), gui.str(name, "settings")
|
||||||
|
))
|
||||||
|
end
|
||||||
|
|
||||||
|
function on_open()
|
||||||
|
create_setting("chunks.load-distance", "Load Distance", 1)
|
||||||
|
create_setting("chunks.load-speed", "Load Speed", 1)
|
||||||
|
create_setting("graphics.fog-curve", "Fog Curve", 0.1)
|
||||||
|
create_setting("graphics.gamma", "Gamma", 0.05)
|
||||||
|
create_setting("camera.fov", "FOV", 1, "°")
|
||||||
|
create_checkbox("display.fullscreen", "Fullscreen")
|
||||||
|
create_checkbox("display.vsync", "V-Sync")
|
||||||
|
create_checkbox("graphics.backlight", "Backlight")
|
||||||
|
create_checkbox("camera.shaking", "Camera Shaking")
|
||||||
|
end
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<panel size='400' padding='8' interval='1' color='#00000080'>
|
||||||
|
<label id='title_label'>???</label>
|
||||||
|
<label id='progress_label'>-</label>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
function on_progress(done, total)
|
||||||
|
local progress = done / total
|
||||||
|
document.progress_label.text = string.format(
|
||||||
|
"%s/%s (%s%%)", done, total, math.floor(progress*100)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function on_open(title)
|
||||||
|
document.title_label.text = title
|
||||||
|
end
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<panel size='500' color='#00000080' padding='8' context='menu'>
|
||||||
|
<label>@missing-content</label>
|
||||||
|
<panel id='content_panel' size='480,100' color='#00000080' scrollable='true' max-length='400'>
|
||||||
|
<!-- content is generated in script -->
|
||||||
|
</panel>
|
||||||
|
<button onclick='menu:back()'>@Back to Main Menu</button>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
function on_open(report)
|
||||||
|
for i, entry in ipairs(report.content) do
|
||||||
|
document.content_panel:add(gui.template("content_entry", entry))
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<panel size='400,40' padding='4' color='0' orientation='horizontal'>
|
||||||
|
<bindbox binding='%{id}'/>
|
||||||
|
<label margin='6'>%{name}</label>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<panel size='500,20' color='0' orientation='horizontal' padding='2'>
|
||||||
|
<label color='#80808080'>[%{type}]</label>
|
||||||
|
<label color='#FF333380'>"%{name}</label>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<container onclick='%{callback}' size='80,30' hover-color='#FFFFFF10'>
|
||||||
|
<label pos='80,4' size='300,25' color='#FFFFFF80' align='right'>[%{id}]</label>
|
||||||
|
<label pos='0,8'>%{name}</label>
|
||||||
|
</container>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<container id='pack_%{id}' onclick='%{callback}' size='0,80' color='#00000040' hover-color='#00000080' z-index="%{index}">
|
||||||
|
<label color='#FFFFFF80' size='300,25' align='right' gravity='top-right'>
|
||||||
|
[%{id_verbose}]
|
||||||
|
</label>
|
||||||
|
<label pos='78,6'>%{title}</label>
|
||||||
|
<label if='%{creator}' color='#CCFFE5B2' size='300,20' align='right'
|
||||||
|
gravity='bottom-right'>
|
||||||
|
%{creator}
|
||||||
|
</label>
|
||||||
|
<label if='%{error}' pos='80,28' size='355,50' multiline='true' color='#FF4040'>%{error}</label>
|
||||||
|
<label ifnot='%{error}' pos='80,28' size='355,50' multiline='true' color='#FFFFFFB2'>
|
||||||
|
%{description}
|
||||||
|
</label>
|
||||||
|
<image pos='8,8' src='%{icon}' size='64'/>
|
||||||
|
</container>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<panel color='0' context='settings'>
|
||||||
|
<label id='%{id}.L' margin='0,3,0,0'>%{name}: %{value}%{postfix}</label>
|
||||||
|
<trackbar
|
||||||
|
value='%{value}' min='%{min}' max='%{max}' step='%{step}'
|
||||||
|
consumer='function(x) update_setting(x, "%{id}", "%{name}", "%{postfix}") end'/>
|
||||||
|
</panel>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<container
|
||||||
|
size='380,66'
|
||||||
|
color='#0F1E2DB2'
|
||||||
|
hover-color='#162B3399'
|
||||||
|
onclick='core.open_world("%{name}")'
|
||||||
|
>
|
||||||
|
<image pos='1' src='%{icon}' size='96,64'></image>
|
||||||
|
<label pos='104,8'>%{name}</label>
|
||||||
|
<button margin='4'
|
||||||
|
gravity='center-right'
|
||||||
|
color='#00000000'
|
||||||
|
hover-color='#FFFFFF2B'
|
||||||
|
padding='0'
|
||||||
|
onclick='core.delete_world("%{name}")'>
|
||||||
|
<image src='gui/delete_icon' size='32,32' color='#FFFFFF50'/>
|
||||||
|
</button>
|
||||||
|
</container>
|
||||||
@@ -11,4 +11,3 @@
|
|||||||
"gui/crosshair"
|
"gui/crosshair"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,9 @@ events = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function events.on(event, func)
|
function events.on(event, func)
|
||||||
events.handlers[event] = events.handlers[event] or {}
|
-- why an array? length is always = 1
|
||||||
|
-- FIXME: temporary fixed
|
||||||
|
events.handlers[event] = {} -- events.handlers[event] or {}
|
||||||
table.insert(events.handlers[event], func)
|
table.insert(events.handlers[event], func)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -175,11 +177,105 @@ Document = {}
|
|||||||
function Document.new(docname)
|
function Document.new(docname)
|
||||||
return setmetatable({name=docname}, {
|
return setmetatable({name=docname}, {
|
||||||
__index=function(self, k)
|
__index=function(self, k)
|
||||||
return Element.new(self.name, k)
|
local elem = Element.new(self.name, k)
|
||||||
|
rawset(self, k, elem)
|
||||||
|
return elem
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
_GUI_ROOT = Document.new("core:root")
|
||||||
|
_MENU = _GUI_ROOT.menu
|
||||||
|
menu = _MENU
|
||||||
|
|
||||||
|
local __post_runnables = {}
|
||||||
|
|
||||||
|
function __process_post_runnables()
|
||||||
|
if #__post_runnables then
|
||||||
|
for _, func in ipairs(__post_runnables) do
|
||||||
|
func()
|
||||||
|
end
|
||||||
|
__post_runnables = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function time.post_runnable(runnable)
|
||||||
|
table.insert(__post_runnables, runnable)
|
||||||
|
end
|
||||||
|
|
||||||
|
function gui.template(name, params)
|
||||||
|
local text = file.read(file.find("layouts/templates/"..name..".xml"))
|
||||||
|
for k,v in pairs(params) do
|
||||||
|
local arg = tostring(v):gsub("'", "\\'"):gsub('"', '\\"')
|
||||||
|
text = text:gsub("(%%{"..k.."})", arg)
|
||||||
|
end
|
||||||
|
text = text:gsub("if%s*=%s*'%%{%w+}'", "if=''")
|
||||||
|
text = text:gsub("if%s*=%s*\"%%{%w+}\"", "if=\"\"")
|
||||||
|
-- remove unsolved properties: attr='%{var}'
|
||||||
|
text = text:gsub("%w+%s*=%s*'%%{%w+}'%s?", "")
|
||||||
|
text = text:gsub("%w+%s*=%s*\"%%{%w+}\"%s?", "")
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
|
||||||
|
session = {
|
||||||
|
entries={}
|
||||||
|
}
|
||||||
|
|
||||||
|
function session.get_entry(name)
|
||||||
|
local entry = session.entries[name]
|
||||||
|
if entry == nil then
|
||||||
|
entry = {}
|
||||||
|
session.entries[name] = entry
|
||||||
|
end
|
||||||
|
return entry
|
||||||
|
end
|
||||||
|
|
||||||
|
function session.reset_entry(name)
|
||||||
|
session.entries[name] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function timeit(func, ...)
|
||||||
|
local tm = time.uptime()
|
||||||
|
func(...)
|
||||||
|
print("[time mcs]", (time.uptime()-tm) * 1000000)
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.has(t, x)
|
||||||
|
for i,v in ipairs(t) do
|
||||||
|
if v == x then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.index(t, x)
|
||||||
|
for i,v in ipairs(t) do
|
||||||
|
if v == x then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.remove_value(t, x)
|
||||||
|
local index = table.index(t, x)
|
||||||
|
if index ~= -1 then
|
||||||
|
table.remove(t, index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.tostring(t)
|
||||||
|
local s = '['
|
||||||
|
for i,v in ipairs(t) do
|
||||||
|
s = s..tostring(v)
|
||||||
|
if i < #t then
|
||||||
|
s = s..', '
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return s..']'
|
||||||
|
end
|
||||||
|
|
||||||
-- Deprecated functions
|
-- Deprecated functions
|
||||||
block_index = block.index
|
block_index = block.index
|
||||||
block_name = block.name
|
block_name = block.name
|
||||||
|
|||||||
@@ -13,44 +13,44 @@ error.dependency-not-found=Die verwendete Abhängigkeit wurde nicht gefunden
|
|||||||
pack.remove-confirm=Alle vom Paket bereitgestellten Inhalte (dauerhaft) aus der Welt löschen?
|
pack.remove-confirm=Alle vom Paket bereitgestellten Inhalte (dauerhaft) aus der Welt löschen?
|
||||||
|
|
||||||
# Меню
|
# Меню
|
||||||
|
menu.Apply=Anwenden
|
||||||
|
menu.Audio=Klang
|
||||||
|
menu.Back to Main Menu=Zurück zum Menü
|
||||||
|
menu.Content Error=Inhaltsfehler
|
||||||
|
menu.Content=Inhalt
|
||||||
|
menu.Continue=Weitermachen
|
||||||
|
menu.Controls=Kontrolle
|
||||||
|
menu.Create World=Erschaffe eine Welt
|
||||||
|
menu.missing-content=Fehlender Inhalt!
|
||||||
menu.New World=Neue Welt
|
menu.New World=Neue Welt
|
||||||
menu.Quit=Ausfahrt
|
menu.Quit=Ausfahrt
|
||||||
menu.Continue=Weitermachen
|
|
||||||
menu.Save and Quit to Menu=Speichern und zum Menü zurückkehren
|
menu.Save and Quit to Menu=Speichern und zum Menü zurückkehren
|
||||||
menu.missing-content=Fehlender Inhalt!
|
|
||||||
menu.Content Error=Inhaltsfehler
|
|
||||||
menu.Controls=Kontrolle
|
|
||||||
menu.Back to Main Menu=Zurück zum Menü
|
|
||||||
menu.Settings=Einstellungen
|
menu.Settings=Einstellungen
|
||||||
menu.Content=Inhalt
|
|
||||||
menu.Audio=Klang
|
|
||||||
world.Seed=Mais
|
world.Seed=Mais
|
||||||
world.Name=Name
|
world.Name=Name
|
||||||
|
|
||||||
world.World generator=Weltgenerator
|
world.World generator=Weltgenerator
|
||||||
world.generators.default=Normal
|
world.generators.default=Normal
|
||||||
world.generators.flat=Wohnung
|
world.generators.flat=Wohnung
|
||||||
menu.Create World=Erschaffe eine Welt
|
world.Create World=Welt Erschaffen
|
||||||
|
|
||||||
world.convert-request=Es gibt Änderungen in den Indizes! Die Welt bekehren?
|
world.convert-request=Es gibt Änderungen in den Indizes! Die Welt bekehren?
|
||||||
world.delete-confirm=Die Welt dauerhaft löschen?
|
world.delete-confirm=Die Welt dauerhaft löschen?
|
||||||
|
|
||||||
# Настройки
|
# Настройки
|
||||||
|
settings.Ambient=Hintergrund
|
||||||
|
settings.Backlight=Hintergrundbeleuchtung
|
||||||
|
settings.Camera Shaking=Wackelnde Kamera
|
||||||
|
settings.Fog Curve=Nebelkurve
|
||||||
|
settings.FOV=Sichtlinie
|
||||||
|
settings.Language=Sprache
|
||||||
settings.Load Distance=Ladeentfernung
|
settings.Load Distance=Ladeentfernung
|
||||||
settings.Load Speed=Download-Geschwindigkeit
|
settings.Load Speed=Download-Geschwindigkeit
|
||||||
settings.Fog Curve=Nebelkurve
|
|
||||||
settings.Backlight=Hintergrundbeleuchtung
|
|
||||||
settings.V-Sync=Vertikale Synchronisation
|
|
||||||
settings.Camera Shaking=Wackelnde Kamera
|
|
||||||
settings.Master Volume=Allgemeine Lautstärke
|
settings.Master Volume=Allgemeine Lautstärke
|
||||||
|
settings.Mouse Sensitivity=Maus-Empfindlichkeit
|
||||||
|
settings.Music=Musik
|
||||||
settings.Regular Sounds=Normale Geräusche
|
settings.Regular Sounds=Normale Geräusche
|
||||||
settings.UI Sounds=Interface-Sounds
|
settings.UI Sounds=Interface-Sounds
|
||||||
settings.Ambient=Hintergrund
|
settings.V-Sync=Vertikale Synchronisation
|
||||||
settings.Music=Musik
|
|
||||||
|
|
||||||
settings.FOV=Sichtlinie
|
|
||||||
settings.Mouse Sensitivity=Maus-Empfindlichkeit
|
|
||||||
settings.Language=Sprache
|
|
||||||
|
|
||||||
# Управление
|
# Управление
|
||||||
movement.forward=Vorwärts
|
movement.forward=Vorwärts
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Menu
|
# Menu
|
||||||
menu.missing-content=Missing Content!
|
menu.missing-content=Missing Content!
|
||||||
world.convert-request=Content indices have changed! Convert world files?
|
world.convert-request=Content indices have changed! Convert world files?
|
||||||
pack.remove-confirm=Do you want to erase all pack content from the world forever?
|
pack.remove-confirm=Do you want to erase all pack(s) content from the world forever?
|
||||||
error.pack-not-found=Could not to find pack
|
error.pack-not-found=Could not to find pack
|
||||||
error.dependency-not-found=Dependency pack is not found
|
error.dependency-not-found=Dependency pack is not found
|
||||||
world.delete-confirm=Do you want to delete world forever?
|
world.delete-confirm=Do you want to delete world forever?
|
||||||
@@ -24,4 +24,4 @@ player.build=Place Block
|
|||||||
player.flight=Flight
|
player.flight=Flight
|
||||||
player.noclip=No-clip
|
player.noclip=No-clip
|
||||||
camera.zoom=Zoom
|
camera.zoom=Zoom
|
||||||
camera.mode=Switch Camera Mode
|
camera.mode=Switch Camera Mode
|
||||||
|
|||||||
@@ -5,38 +5,53 @@ Ok=OK
|
|||||||
Cancel=Anulowanie
|
Cancel=Anulowanie
|
||||||
Back=Powrót
|
Back=Powrót
|
||||||
Continue=Kontynuacja
|
Continue=Kontynuacja
|
||||||
|
Add=Dodać
|
||||||
|
Converting world...=Konwersja świata w toku...
|
||||||
|
|
||||||
error.pack-not-found=Nie udało się znaleźć pakietu
|
error.pack-not-found=Nie udało się znaleźć pakietu
|
||||||
|
|
||||||
# Menu
|
# Menu
|
||||||
menu.New World=Nowy Świat
|
menu.Apply=Zastosować
|
||||||
menu.Quit=Wyjście
|
menu.Audio=Dźwięki
|
||||||
menu.Continue=Kontynuacja
|
|
||||||
menu.Save and Quit to Menu=Zapisz i wyjdź do menu
|
|
||||||
menu.missing-content=Brak treści!
|
|
||||||
menu.Controls=Zarządzanie
|
|
||||||
menu.Back to Main Menu=Powrót do menu
|
menu.Back to Main Menu=Powrót do menu
|
||||||
menu.Settings=Ustawienia
|
|
||||||
menu.Content=Treść
|
menu.Content=Treść
|
||||||
|
menu.Continue=Kontynuacja
|
||||||
|
menu.Controls=Zarządzanie
|
||||||
|
menu.Graphics=Grafika
|
||||||
|
menu.Create World=Stwórz świat
|
||||||
|
menu.missing-content=Brakująca treść!
|
||||||
|
menu.New World=Nowy Świat
|
||||||
|
menu.Page not found=Strona nie znaleziona
|
||||||
|
menu.Quit=Wyjście
|
||||||
|
menu.Save and Quit to Menu=Zapisz i wyjdź do menu
|
||||||
|
menu.Settings=Ustawienia
|
||||||
|
|
||||||
world.Seed=Ziarno
|
world.Seed=Ziarno
|
||||||
world.Name=Nazwa
|
world.Name=Nazwa
|
||||||
menu.Create World=Stwórz świat
|
|
||||||
|
|
||||||
world.World generator=Generator światła
|
world.World generator=Generator światła
|
||||||
world.generators.default=Ekstremalne
|
world.generators.default=Ekstremalne
|
||||||
world.generators.flat=Mieszkanie
|
world.generators.flat=Mieszkanie
|
||||||
|
world.Create World=Stwórz świat
|
||||||
world.convert-request=Szykują się zmiany w indeksach! Przekształcić świat?
|
world.convert-request=Szykują się zmiany w indeksach! Przekształcić świat?
|
||||||
|
world.delete-confirm=Trwale usunąć świat?
|
||||||
|
|
||||||
# Ustawienia
|
# Ustawienia
|
||||||
|
settings.Ambient=Tło
|
||||||
|
settings.Backlight=Podświetlenie
|
||||||
|
settings.Camera Shaking=Drżąca kamera
|
||||||
|
settings.Fog Curve=Krzywa mgły
|
||||||
|
settings.FOV=Wzrok
|
||||||
|
settings.Fullscreen=Pełny ekran
|
||||||
|
settings.Gamma=Gamma
|
||||||
|
settings.Language=Język
|
||||||
settings.Load Distance=Odległość ładowania
|
settings.Load Distance=Odległość ładowania
|
||||||
settings.Load Speed=Prędkość pobierania
|
settings.Load Speed=Prędkość pobierania
|
||||||
settings.Fog Curve=Krzywa mgły
|
settings.Master Volume=Głośność główna
|
||||||
settings.Backlight=Podświetlenie
|
|
||||||
settings.V-Sync=Synchronizacja pionowa
|
|
||||||
|
|
||||||
settings.FOV=Wzrok
|
|
||||||
settings.Mouse Sensitivity=Wrażliwość myszy
|
settings.Mouse Sensitivity=Wrażliwość myszy
|
||||||
settings.Language=Język
|
settings.Music=Muzyka
|
||||||
|
settings.Regular Sounds=Normalne dźwięki
|
||||||
|
settings.UI Sounds=Dźwięki interfejsu
|
||||||
|
settings.V-Sync=Synchronizacja pionowa
|
||||||
|
|
||||||
# Zarządzanie
|
# Zarządzanie
|
||||||
movement.forward=Naprzód
|
movement.forward=Naprzód
|
||||||
|
|||||||
@@ -10,47 +10,50 @@ Converting world...=Выполняется конвертация мира...
|
|||||||
|
|
||||||
error.pack-not-found=Не удалось найти пакет
|
error.pack-not-found=Не удалось найти пакет
|
||||||
error.dependency-not-found=Используемая зависимость не найдена
|
error.dependency-not-found=Используемая зависимость не найдена
|
||||||
pack.remove-confirm=Удалить весь поставляемый паком контент из мира (безвозвратно)?
|
pack.remove-confirm=Удалить весь поставляемый паком/паками контент из мира (безвозвратно)?
|
||||||
|
|
||||||
# Меню
|
# Меню
|
||||||
menu.New World=Новый Мир
|
menu.Apply=Применить
|
||||||
menu.Quit=Выход
|
|
||||||
menu.Continue=Продолжить
|
|
||||||
menu.Save and Quit to Menu=Сохранить и Выйти в Меню
|
|
||||||
menu.missing-content=Отсутствует Контент!
|
|
||||||
menu.Content Error=Ошибка Контента
|
|
||||||
menu.Controls=Управление
|
|
||||||
menu.Back to Main Menu=Вернуться в Меню
|
|
||||||
menu.Settings=Настройки
|
|
||||||
menu.Content=Контент
|
|
||||||
menu.Audio=Звук
|
menu.Audio=Звук
|
||||||
|
menu.Back to Main Menu=Вернуться в Меню
|
||||||
|
menu.Content Error=Ошибка Контента
|
||||||
|
menu.Content=Контент
|
||||||
|
menu.Continue=Продолжить
|
||||||
|
menu.Controls=Управление
|
||||||
|
menu.Graphics=Графика
|
||||||
|
menu.missing-content=Отсутствует Контент!
|
||||||
|
menu.New World=Новый Мир
|
||||||
|
menu.Page not found=Страница не найдена
|
||||||
|
menu.Quit=Выход
|
||||||
|
menu.Save and Quit to Menu=Сохранить и Выйти в Меню
|
||||||
|
menu.Settings=Настройки
|
||||||
|
|
||||||
world.Seed=Зерно
|
world.Seed=Зерно
|
||||||
world.Name=Название
|
world.Name=Название
|
||||||
|
|
||||||
world.World generator=Генератор мира
|
world.World generator=Генератор мира
|
||||||
world.generators.default=Обычный
|
world.generators.default=Обычный
|
||||||
world.generators.flat=Плоский
|
world.generators.flat=Плоский
|
||||||
menu.Create World=Создать Мир
|
world.Create World=Создать Мир
|
||||||
|
|
||||||
world.convert-request=Есть изменения в индексах! Конвертировать мир?
|
world.convert-request=Есть изменения в индексах! Конвертировать мир?
|
||||||
world.delete-confirm=Удалить мир безвозвратно?
|
world.delete-confirm=Удалить мир безвозвратно?
|
||||||
|
|
||||||
# Настройки
|
# Настройки
|
||||||
|
settings.Ambient=Фон
|
||||||
|
settings.Backlight=Подсветка
|
||||||
|
settings.Camera Shaking=Тряска Камеры
|
||||||
|
settings.Fog Curve=Кривая Тумана
|
||||||
|
settings.FOV=Поле Зрения
|
||||||
|
settings.Fullscreen=Полный экран
|
||||||
|
settings.Gamma=Гамма
|
||||||
|
settings.Language=Язык
|
||||||
settings.Load Distance=Дистанция Загрузки
|
settings.Load Distance=Дистанция Загрузки
|
||||||
settings.Load Speed=Скорость Загрузки
|
settings.Load Speed=Скорость Загрузки
|
||||||
settings.Fog Curve=Кривая Тумана
|
|
||||||
settings.Backlight=Подсветка
|
|
||||||
settings.V-Sync=Вертикальная Синхронизация
|
|
||||||
settings.Camera Shaking=Тряска Камеры
|
|
||||||
settings.Master Volume=Общая Громкость
|
settings.Master Volume=Общая Громкость
|
||||||
|
settings.Mouse Sensitivity=Чувствительность Мыши
|
||||||
|
settings.Music=Музыка
|
||||||
settings.Regular Sounds=Обычные Звуки
|
settings.Regular Sounds=Обычные Звуки
|
||||||
settings.UI Sounds=Звуки Интерфейса
|
settings.UI Sounds=Звуки Интерфейса
|
||||||
settings.Ambient=Фон
|
settings.V-Sync=Вертикальная Синхронизация
|
||||||
settings.Music=Музыка
|
|
||||||
|
|
||||||
settings.FOV=Поле Зрения
|
|
||||||
settings.Mouse Sensitivity=Чувствительность Мыши
|
|
||||||
settings.Language=Язык
|
|
||||||
|
|
||||||
# Управление
|
# Управление
|
||||||
movement.forward=Вперёд
|
movement.forward=Вперёд
|
||||||
@@ -67,4 +70,4 @@ player.attack=Атаковать / Сломать
|
|||||||
player.build=Поставить Блок
|
player.build=Поставить Блок
|
||||||
player.flight=Полёт
|
player.flight=Полёт
|
||||||
camera.zoom=Приближение
|
camera.zoom=Приближение
|
||||||
camera.mode=Сменить Режим Камеры
|
camera.mode=Сменить Режим Камеры
|
||||||
|
|||||||
@@ -5,19 +5,26 @@ Ok=Гаразд
|
|||||||
Cancel=Скасувати
|
Cancel=Скасувати
|
||||||
Back=Назад
|
Back=Назад
|
||||||
Continue=Продовжити
|
Continue=Продовжити
|
||||||
|
Add=Додати
|
||||||
|
Converting world...=Виконується конвертація світу...
|
||||||
|
|
||||||
error.pack-not-found=Не вдалося знайти пакет
|
error.pack-not-found=Не вдалося знайти пакет
|
||||||
|
|
||||||
# Меню
|
# Меню
|
||||||
menu.New World=Новий Світ
|
menu.Apply=Застосувати
|
||||||
menu.Quit=Вихід
|
menu.Audio=Звук
|
||||||
menu.Continue=Продовжити
|
|
||||||
menu.Save and Quit to Menu=Зберегти і Вийти в Меню
|
|
||||||
menu.missing-content=Відсутній Контент!
|
|
||||||
menu.Controls=Керування
|
|
||||||
menu.Back to Main Menu=Повернутися до Меню
|
menu.Back to Main Menu=Повернутися до Меню
|
||||||
menu.Settings=Налаштування
|
menu.Content Error=Помилка Контенту
|
||||||
menu.Content=Контент
|
menu.Content=Контент
|
||||||
|
menu.Continue=Продовжити
|
||||||
|
menu.Controls=Керування
|
||||||
|
menu.Graphics=Графіка
|
||||||
|
menu.missing-content=Відсутній Контент!
|
||||||
|
menu.New World=Новий Світ
|
||||||
|
menu.Page not found=Сторінка не знайдена
|
||||||
|
menu.Quit=Вихід
|
||||||
|
menu.Save and Quit to Menu=Зберегти і Вийти в Меню
|
||||||
|
menu.Settings=Налаштування
|
||||||
world.Seed=Зерно
|
world.Seed=Зерно
|
||||||
world.Name=Назва
|
world.Name=Назва
|
||||||
menu.Create World=Створити Світ
|
menu.Create World=Створити Світ
|
||||||
@@ -28,15 +35,22 @@ world.generators.flat=Плоскі
|
|||||||
world.convert-request=Є зміни в індексах! Конвертувати світ?
|
world.convert-request=Є зміни в індексах! Конвертувати світ?
|
||||||
|
|
||||||
# Налаштування
|
# Налаштування
|
||||||
|
settings.Ambient=Фон
|
||||||
|
settings.Backlight=Підсвічування
|
||||||
|
settings.Camera Shaking=Тряска Камери
|
||||||
|
settings.Fog Curve=Крива Туману
|
||||||
|
settings.FOV=Поле зору
|
||||||
|
settings.Fullscreen=Повний екран
|
||||||
|
settings.Gamma=Гамма
|
||||||
|
settings.Language=Мова
|
||||||
settings.Load Distance=Дистанція Завантаження
|
settings.Load Distance=Дистанція Завантаження
|
||||||
settings.Load Speed=Швидкість Завантаження
|
settings.Load Speed=Швидкість Завантаження
|
||||||
settings.Fog Curve=Крива Туману
|
settings.Master Volume=Загальна Гучність
|
||||||
settings.Backlight=Підсвічування
|
|
||||||
settings.V-Sync=Вертикальна Синхронізація
|
|
||||||
|
|
||||||
settings.FOV=Поле зору
|
|
||||||
settings.Mouse Sensitivity=Чутливість Миші
|
settings.Mouse Sensitivity=Чутливість Миші
|
||||||
settings.Language=Мова
|
settings.Music=Музика
|
||||||
|
settings.Regular Sounds=Звичайні Звуки
|
||||||
|
settings.UI Sounds=Звуки інтерфейсу
|
||||||
|
settings.V-Sync=Вертикальна Синхронізація
|
||||||
|
|
||||||
# Керування
|
# Керування
|
||||||
movement.forward=Уперед
|
movement.forward=Уперед
|
||||||
|
|||||||
|
After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 132 B After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 953 B |
|
After Width: | Height: | Size: 510 B |
|
After Width: | Height: | Size: 5.6 KiB |
@@ -1,112 +1,87 @@
|
|||||||
#include "Assets.h"
|
#include "Assets.hpp"
|
||||||
|
|
||||||
#include "../audio/audio.h"
|
#include "../audio/audio.hpp"
|
||||||
#include "../graphics/Texture.h"
|
#include "../graphics/core/Texture.hpp"
|
||||||
#include "../graphics/Shader.h"
|
#include "../graphics/core/Shader.hpp"
|
||||||
#include "../graphics/Atlas.h"
|
#include "../graphics/core/Atlas.hpp"
|
||||||
#include "../graphics/Font.h"
|
#include "../graphics/core/Font.hpp"
|
||||||
#include "../frontend/UiDocument.h"
|
#include "../frontend/UiDocument.hpp"
|
||||||
#include "../logic/scripting/scripting.h"
|
#include "../logic/scripting/scripting.hpp"
|
||||||
|
|
||||||
Assets::~Assets() {
|
Assets::~Assets() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* Assets::getTexture(std::string name) const {
|
Texture* Assets::getTexture(std::string name) const {
|
||||||
auto found = textures.find(name);
|
auto found = textures.find(name);
|
||||||
if (found == textures.end())
|
if (found == textures.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(Texture* texture, std::string name){
|
void Assets::store(Texture* texture, std::string name){
|
||||||
textures.emplace(name, texture);
|
textures.emplace(name, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Shader* Assets::getShader(std::string name) const{
|
Shader* Assets::getShader(std::string name) const{
|
||||||
auto found = shaders.find(name);
|
auto found = shaders.find(name);
|
||||||
if (found == shaders.end())
|
if (found == shaders.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(Shader* shader, std::string name){
|
void Assets::store(Shader* shader, std::string name){
|
||||||
shaders.emplace(name, shader);
|
shaders.emplace(name, shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
Font* Assets::getFont(std::string name) const {
|
Font* Assets::getFont(std::string name) const {
|
||||||
auto found = fonts.find(name);
|
auto found = fonts.find(name);
|
||||||
if (found == fonts.end())
|
if (found == fonts.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(Font* font, std::string name){
|
void Assets::store(Font* font, std::string name){
|
||||||
fonts.emplace(name, font);
|
fonts.emplace(name, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
Atlas* Assets::getAtlas(std::string name) const {
|
Atlas* Assets::getAtlas(std::string name) const {
|
||||||
auto found = atlases.find(name);
|
auto found = atlases.find(name);
|
||||||
if (found == atlases.end())
|
if (found == atlases.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(Atlas* atlas, std::string name){
|
void Assets::store(Atlas* atlas, std::string name){
|
||||||
atlases.emplace(name, atlas);
|
atlases.emplace(name, atlas);
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::Sound* Assets::getSound(std::string name) const {
|
audio::Sound* Assets::getSound(std::string name) const {
|
||||||
auto found = sounds.find(name);
|
auto found = sounds.find(name);
|
||||||
if (found == sounds.end())
|
if (found == sounds.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(audio::Sound* sound, std::string name) {
|
void Assets::store(audio::Sound* sound, std::string name) {
|
||||||
sounds.emplace(name, sound);
|
sounds.emplace(name, sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<TextureAnimation>& Assets::getAnimations() {
|
const std::vector<TextureAnimation>& Assets::getAnimations() {
|
||||||
return animations;
|
return animations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(const TextureAnimation& animation) {
|
void Assets::store(const TextureAnimation& animation) {
|
||||||
animations.emplace_back(animation);
|
animations.emplace_back(animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
UiDocument* Assets::getLayout(std::string name) const {
|
UiDocument* Assets::getLayout(std::string name) const {
|
||||||
auto found = layouts.find(name);
|
auto found = layouts.find(name);
|
||||||
if (found == layouts.end())
|
if (found == layouts.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assets::store(UiDocument* layout, std::string name) {
|
void Assets::store(UiDocument* layout, std::string name) {
|
||||||
layouts.emplace(name, layout);
|
layouts[name] = std::shared_ptr<UiDocument>(layout);
|
||||||
}
|
|
||||||
|
|
||||||
void Assets::extend(const Assets& assets) {
|
|
||||||
for (auto entry : assets.textures) {
|
|
||||||
textures[entry.first] = entry.second;
|
|
||||||
}
|
|
||||||
for (auto entry : assets.shaders) {
|
|
||||||
shaders[entry.first] = entry.second;
|
|
||||||
}
|
|
||||||
for (auto entry : assets.fonts) {
|
|
||||||
fonts[entry.first] = entry.second;
|
|
||||||
}
|
|
||||||
for (auto entry : assets.atlases) {
|
|
||||||
atlases[entry.first] = entry.second;
|
|
||||||
}
|
|
||||||
for (auto entry : assets.layouts) {
|
|
||||||
layouts[entry.first] = entry.second;
|
|
||||||
}
|
|
||||||
for (auto entry : assets.sounds) {
|
|
||||||
sounds[entry.first] = entry.second;
|
|
||||||
}
|
|
||||||
animations.clear();
|
|
||||||
for (auto entry : assets.animations) {
|
|
||||||
animations.emplace_back(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef ASSETS_ASSETS_H_
|
|
||||||
#define ASSETS_ASSETS_H_
|
|
||||||
|
|
||||||
#include "../graphics/TextureAnimation.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class Texture;
|
|
||||||
class Shader;
|
|
||||||
class Font;
|
|
||||||
class Atlas;
|
|
||||||
class UiDocument;
|
|
||||||
|
|
||||||
namespace audio {
|
|
||||||
class Sound;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Assets {
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Font>> fonts;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Atlas>> atlases;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<UiDocument>> layouts;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<audio::Sound>> sounds;
|
|
||||||
std::vector<TextureAnimation> animations;
|
|
||||||
public:
|
|
||||||
~Assets();
|
|
||||||
Texture* getTexture(std::string name) const;
|
|
||||||
void store(Texture* texture, std::string name);
|
|
||||||
|
|
||||||
Shader* getShader(std::string name) const;
|
|
||||||
void store(Shader* shader, std::string name);
|
|
||||||
|
|
||||||
Font* getFont(std::string name) const;
|
|
||||||
void store(Font* font, std::string name);
|
|
||||||
|
|
||||||
Atlas* getAtlas(std::string name) const;
|
|
||||||
void store(Atlas* atlas, std::string name);
|
|
||||||
|
|
||||||
audio::Sound* getSound(std::string name) const;
|
|
||||||
void store(audio::Sound* sound, std::string name);
|
|
||||||
|
|
||||||
const std::vector<TextureAnimation>& getAnimations();
|
|
||||||
void store(const TextureAnimation& animation);
|
|
||||||
|
|
||||||
UiDocument* getLayout(std::string name) const;
|
|
||||||
void store(UiDocument* layout, std::string name);
|
|
||||||
|
|
||||||
void extend(const Assets& assets);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* ASSETS_ASSETS_H_ */
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#ifndef ASSETS_ASSETS_HPP_
|
||||||
|
#define ASSETS_ASSETS_HPP_
|
||||||
|
|
||||||
|
#include "../graphics/core/TextureAnimation.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Texture;
|
||||||
|
class Shader;
|
||||||
|
class Font;
|
||||||
|
class Atlas;
|
||||||
|
class Assets;
|
||||||
|
class UiDocument;
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
class Sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace assetload {
|
||||||
|
/// @brief final work to do in the main thread
|
||||||
|
using postfunc = std::function<void(Assets*)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Assets {
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Font>> fonts;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Atlas>> atlases;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<UiDocument>> layouts;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<audio::Sound>> sounds;
|
||||||
|
std::vector<TextureAnimation> animations;
|
||||||
|
public:
|
||||||
|
Assets() {}
|
||||||
|
Assets(const Assets&) = delete;
|
||||||
|
~Assets();
|
||||||
|
|
||||||
|
Texture* getTexture(std::string name) const;
|
||||||
|
void store(Texture* texture, std::string name);
|
||||||
|
|
||||||
|
Shader* getShader(std::string name) const;
|
||||||
|
void store(Shader* shader, std::string name);
|
||||||
|
|
||||||
|
Font* getFont(std::string name) const;
|
||||||
|
void store(Font* font, std::string name);
|
||||||
|
|
||||||
|
Atlas* getAtlas(std::string name) const;
|
||||||
|
void store(Atlas* atlas, std::string name);
|
||||||
|
|
||||||
|
audio::Sound* getSound(std::string name) const;
|
||||||
|
void store(audio::Sound* sound, std::string name);
|
||||||
|
|
||||||
|
const std::vector<TextureAnimation>& getAnimations();
|
||||||
|
void store(const TextureAnimation& animation);
|
||||||
|
|
||||||
|
UiDocument* getLayout(std::string name) const;
|
||||||
|
void store(UiDocument* layout, std::string name);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ASSETS_ASSETS_HPP_
|
||||||
@@ -1,58 +1,74 @@
|
|||||||
#include "AssetsLoader.h"
|
#include "AssetsLoader.hpp"
|
||||||
#include "Assets.h"
|
|
||||||
|
|
||||||
#include "assetload_funcs.h"
|
#include "Assets.hpp"
|
||||||
|
#include "assetload_funcs.hpp"
|
||||||
|
#include "../util/ThreadPool.hpp"
|
||||||
|
#include "../constants.hpp"
|
||||||
|
#include "../data/dynamic.hpp"
|
||||||
|
#include "../debug/Logger.hpp"
|
||||||
|
#include "../coders/imageio.hpp"
|
||||||
|
#include "../files/files.hpp"
|
||||||
|
#include "../files/engine_paths.hpp"
|
||||||
|
#include "../content/Content.hpp"
|
||||||
|
#include "../content/ContentPack.hpp"
|
||||||
|
#include "../graphics/core/Texture.hpp"
|
||||||
|
#include "../logic/scripting/scripting.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "../constants.h"
|
static debug::Logger logger("assets-loader");
|
||||||
#include "../data/dynamic.h"
|
|
||||||
#include "../files/files.h"
|
|
||||||
#include "../files/engine_paths.h"
|
|
||||||
#include "../content/Content.h"
|
|
||||||
#include "../content/ContentPack.h"
|
|
||||||
#include "../logic/scripting/scripting.h"
|
|
||||||
|
|
||||||
AssetsLoader::AssetsLoader(Assets* assets, const ResPaths* paths)
|
AssetsLoader::AssetsLoader(Assets* assets, const ResPaths* paths)
|
||||||
: assets(assets), paths(paths)
|
: assets(assets), paths(paths)
|
||||||
{
|
{
|
||||||
addLoader(AssetType::shader, assetload::shader);
|
addLoader(AssetType::shader, assetload::shader);
|
||||||
addLoader(AssetType::texture, assetload::texture);
|
addLoader(AssetType::texture, assetload::texture);
|
||||||
addLoader(AssetType::font, assetload::font);
|
addLoader(AssetType::font, assetload::font);
|
||||||
addLoader(AssetType::atlas, assetload::atlas);
|
addLoader(AssetType::atlas, assetload::atlas);
|
||||||
addLoader(AssetType::layout, assetload::layout);
|
addLoader(AssetType::layout, assetload::layout);
|
||||||
addLoader(AssetType::sound, assetload::sound);
|
addLoader(AssetType::sound, assetload::sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetsLoader::addLoader(AssetType tag, aloader_func func) {
|
void AssetsLoader::addLoader(AssetType tag, aloader_func func) {
|
||||||
loaders[tag] = func;
|
loaders[tag] = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetsLoader::add(AssetType tag, const std::string filename, const std::string alias, std::shared_ptr<AssetCfg> settings) {
|
void AssetsLoader::add(AssetType tag, const std::string filename, const std::string alias, std::shared_ptr<AssetCfg> settings) {
|
||||||
entries.push(aloader_entry{tag, filename, alias, settings});
|
entries.push(aloader_entry{tag, filename, alias, settings});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetsLoader::hasNext() const {
|
bool AssetsLoader::hasNext() const {
|
||||||
return !entries.empty();
|
return !entries.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
aloader_func AssetsLoader::getLoader(AssetType tag) {
|
||||||
|
auto found = loaders.find(tag);
|
||||||
|
if (found == loaders.end()) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"unknown asset tag "+std::to_string(static_cast<int>(tag))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetsLoader::loadNext() {
|
bool AssetsLoader::loadNext() {
|
||||||
const aloader_entry& entry = entries.front();
|
const aloader_entry& entry = entries.front();
|
||||||
std::cout << " loading " << entry.filename << " as " << entry.alias << std::endl;
|
logger.info() << "loading " << entry.filename << " as " << entry.alias;
|
||||||
std::cout.flush();
|
try {
|
||||||
auto found = loaders.find(entry.tag);
|
aloader_func loader = getLoader(entry.tag);
|
||||||
if (found == loaders.end()) {
|
auto postfunc = loader(this, paths, entry.filename, entry.alias, entry.config);
|
||||||
std::cerr << "unknown asset tag " << static_cast<int>(entry.tag) << std::endl;
|
postfunc(assets);
|
||||||
return false;
|
entries.pop();
|
||||||
}
|
return true;
|
||||||
aloader_func loader = found->second;
|
} catch (std::runtime_error& err) {
|
||||||
bool status = loader(*this, assets, paths, entry.filename, entry.alias, entry.config);
|
logger.error() << err.what();
|
||||||
entries.pop();
|
entries.pop();
|
||||||
return status;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLayouts(int env, const std::string& prefix, const fs::path& folder, AssetsLoader& loader) {
|
void addLayouts(scriptenv env, const std::string& prefix, const fs::path& folder, AssetsLoader& loader) {
|
||||||
if (!fs::is_directory(folder)) {
|
if (!fs::is_directory(folder)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -117,11 +133,12 @@ void AssetsLoader::processPreloadList(AssetType tag, dynamic::List* list) {
|
|||||||
auto value = list->get(i);
|
auto value = list->get(i);
|
||||||
switch (value->type) {
|
switch (value->type) {
|
||||||
case dynamic::valtype::string:
|
case dynamic::valtype::string:
|
||||||
processPreload(tag, *value->value.str, nullptr);
|
processPreload(tag, std::get<std::string>(value->value), nullptr);
|
||||||
break;
|
break;
|
||||||
case dynamic::valtype::map: {
|
case dynamic::valtype::map: {
|
||||||
auto name = value->value.map->getStr("name");
|
auto map = std::get<dynamic::Map*>(value->value);
|
||||||
processPreload(tag, name, value->value.map);
|
auto name = map->getStr("name");
|
||||||
|
processPreload(tag, name, map);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -161,9 +178,11 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
|||||||
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/menubg", "gui/menubg");
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/menubg", "gui/menubg");
|
||||||
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/delete_icon", "gui/delete_icon");
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/delete_icon", "gui/delete_icon");
|
||||||
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/no_icon", "gui/no_icon");
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/no_icon", "gui/no_icon");
|
||||||
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/no_world_icon", "gui/no_world_icon");
|
||||||
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/warning", "gui/warning");
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/warning", "gui/warning");
|
||||||
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/error", "gui/error");
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/error", "gui/error");
|
||||||
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/cross", "gui/cross");
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/cross", "gui/cross");
|
||||||
|
loader.add(AssetType::texture, TEXTURES_FOLDER+"/gui/refresh", "gui/refresh");
|
||||||
if (content) {
|
if (content) {
|
||||||
loader.processPreloadConfigs(content);
|
loader.processPreloadConfigs(content);
|
||||||
|
|
||||||
@@ -179,13 +198,68 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
|||||||
auto pack = entry.second.get();
|
auto pack = entry.second.get();
|
||||||
auto& info = pack->getInfo();
|
auto& info = pack->getInfo();
|
||||||
fs::path folder = info.folder / fs::path("layouts");
|
fs::path folder = info.folder / fs::path("layouts");
|
||||||
addLayouts(pack->getEnvironment()->getId(), info.id, folder, loader);
|
addLayouts(pack->getEnvironment(), info.id, folder, loader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loader.add(AssetType::atlas, TEXTURES_FOLDER+"/blocks", "blocks");
|
loader.add(AssetType::atlas, TEXTURES_FOLDER+"/blocks", "blocks");
|
||||||
loader.add(AssetType::atlas, TEXTURES_FOLDER+"/items", "items");
|
loader.add(AssetType::atlas, TEXTURES_FOLDER+"/items", "items");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AssetsLoader::loadExternalTexture(
|
||||||
|
Assets* assets,
|
||||||
|
const std::string& name,
|
||||||
|
std::vector<std::filesystem::path> alternatives
|
||||||
|
) {
|
||||||
|
if (assets->getTexture(name) != nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (auto& path : alternatives) {
|
||||||
|
if (fs::exists(path)) {
|
||||||
|
try {
|
||||||
|
auto image = imageio::read(path.string());
|
||||||
|
assets->store(Texture::from(image.get()).release(), name);
|
||||||
|
return true;
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
logger.error() << "error while loading external "
|
||||||
|
<< path.u8string() << ": " << err.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const ResPaths* AssetsLoader::getPaths() const {
|
const ResPaths* AssetsLoader::getPaths() const {
|
||||||
return paths;
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoaderWorker : public util::Worker<aloader_entry, assetload::postfunc> {
|
||||||
|
AssetsLoader* loader;
|
||||||
|
public:
|
||||||
|
LoaderWorker(AssetsLoader* loader) : loader(loader) {
|
||||||
|
}
|
||||||
|
|
||||||
|
assetload::postfunc operator()(const std::shared_ptr<aloader_entry>& entry) override {
|
||||||
|
aloader_func loadfunc = loader->getLoader(entry->tag);
|
||||||
|
return loadfunc(loader, loader->getPaths(), entry->filename, entry->alias, entry->config);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Task> AssetsLoader::startTask(runnable onDone) {
|
||||||
|
auto pool = std::make_shared<
|
||||||
|
util::ThreadPool<aloader_entry, assetload::postfunc>
|
||||||
|
>(
|
||||||
|
"assets-loader-pool",
|
||||||
|
[=](){return std::make_shared<LoaderWorker>(this);},
|
||||||
|
[=](assetload::postfunc& func) {
|
||||||
|
func(assets);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
pool->setOnComplete(onDone);
|
||||||
|
while (!entries.empty()) {
|
||||||
|
const aloader_entry& entry = entries.front();
|
||||||
|
auto ptr = std::make_shared<aloader_entry>(entry);
|
||||||
|
pool->enqueueJob(ptr);
|
||||||
|
entries.pop();
|
||||||
|
}
|
||||||
|
return pool;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
#ifndef ASSETS_ASSETS_LOADER_H
|
|
||||||
#define ASSETS_ASSETS_LOADER_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
namespace dynamic {
|
|
||||||
class Map;
|
|
||||||
class List;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class AssetType {
|
|
||||||
texture,
|
|
||||||
shader,
|
|
||||||
font,
|
|
||||||
atlas,
|
|
||||||
layout,
|
|
||||||
sound
|
|
||||||
};
|
|
||||||
|
|
||||||
class ResPaths;
|
|
||||||
class Assets;
|
|
||||||
class AssetsLoader;
|
|
||||||
class Content;
|
|
||||||
|
|
||||||
struct AssetCfg {
|
|
||||||
virtual ~AssetCfg() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LayoutCfg : AssetCfg {
|
|
||||||
int env;
|
|
||||||
|
|
||||||
LayoutCfg(int env) : env(env) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SoundCfg : AssetCfg {
|
|
||||||
bool keepPCM;
|
|
||||||
|
|
||||||
SoundCfg(bool keepPCM) : keepPCM(keepPCM) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
using aloader_func = std::function<bool(AssetsLoader&, Assets*, const ResPaths*, const std::string&, const std::string&, std::shared_ptr<AssetCfg>)>;
|
|
||||||
|
|
||||||
struct aloader_entry {
|
|
||||||
AssetType tag;
|
|
||||||
const std::string filename;
|
|
||||||
const std::string alias;
|
|
||||||
std::shared_ptr<AssetCfg> config;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AssetsLoader {
|
|
||||||
Assets* assets;
|
|
||||||
std::map<AssetType, aloader_func> loaders;
|
|
||||||
std::queue<aloader_entry> entries;
|
|
||||||
const ResPaths* paths;
|
|
||||||
|
|
||||||
void tryAddSound(std::string name);
|
|
||||||
|
|
||||||
void processPreload(AssetType tag, const std::string& name, dynamic::Map* map);
|
|
||||||
void processPreloadList(AssetType tag, dynamic::List* list);
|
|
||||||
void processPreloadConfig(std::filesystem::path file);
|
|
||||||
void processPreloadConfigs(const Content* content);
|
|
||||||
public:
|
|
||||||
AssetsLoader(Assets* assets, const ResPaths* paths);
|
|
||||||
void addLoader(AssetType tag, aloader_func func);
|
|
||||||
|
|
||||||
/// @brief Enqueue asset load
|
|
||||||
/// @param tag asset type
|
|
||||||
/// @param filename asset file path
|
|
||||||
/// @param alias internal asset name
|
|
||||||
/// @param settings asset loading settings (based on asset type)
|
|
||||||
void add(
|
|
||||||
AssetType tag,
|
|
||||||
const std::string filename,
|
|
||||||
const std::string alias,
|
|
||||||
std::shared_ptr<AssetCfg> settings=nullptr
|
|
||||||
);
|
|
||||||
|
|
||||||
bool hasNext() const;
|
|
||||||
bool loadNext();
|
|
||||||
|
|
||||||
/// @brief Enqueue core and content assets
|
|
||||||
/// @param loader target loader
|
|
||||||
/// @param content engine content
|
|
||||||
static void addDefaults(AssetsLoader& loader, const Content* content);
|
|
||||||
|
|
||||||
const ResPaths* getPaths() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ASSETS_ASSETS_LOADER_H
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
#ifndef ASSETS_ASSETS_LOADER_HPP_
|
||||||
|
#define ASSETS_ASSETS_LOADER_HPP_
|
||||||
|
|
||||||
|
#include "Assets.hpp"
|
||||||
|
#include "../interfaces/Task.hpp"
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
#include "../delegates.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace dynamic {
|
||||||
|
class Map;
|
||||||
|
class List;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class AssetType {
|
||||||
|
texture,
|
||||||
|
shader,
|
||||||
|
font,
|
||||||
|
atlas,
|
||||||
|
layout,
|
||||||
|
sound
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResPaths;
|
||||||
|
class AssetsLoader;
|
||||||
|
class Content;
|
||||||
|
|
||||||
|
struct AssetCfg {
|
||||||
|
virtual ~AssetCfg() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LayoutCfg : AssetCfg {
|
||||||
|
scriptenv env;
|
||||||
|
|
||||||
|
LayoutCfg(scriptenv env) : env(env) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SoundCfg : AssetCfg {
|
||||||
|
bool keepPCM;
|
||||||
|
|
||||||
|
SoundCfg(bool keepPCM) : keepPCM(keepPCM) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
using aloader_func = std::function<assetload::postfunc(
|
||||||
|
AssetsLoader*, // redundant?
|
||||||
|
const ResPaths*,
|
||||||
|
const std::string&,
|
||||||
|
const std::string&,
|
||||||
|
std::shared_ptr<AssetCfg>)
|
||||||
|
>;
|
||||||
|
|
||||||
|
struct aloader_entry {
|
||||||
|
AssetType tag;
|
||||||
|
const std::string filename;
|
||||||
|
const std::string alias;
|
||||||
|
std::shared_ptr<AssetCfg> config;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AssetsLoader {
|
||||||
|
Assets* assets;
|
||||||
|
std::map<AssetType, aloader_func> loaders;
|
||||||
|
std::queue<aloader_entry> entries;
|
||||||
|
const ResPaths* paths;
|
||||||
|
|
||||||
|
void tryAddSound(std::string name);
|
||||||
|
|
||||||
|
void processPreload(AssetType tag, const std::string& name, dynamic::Map* map);
|
||||||
|
void processPreloadList(AssetType tag, dynamic::List* list);
|
||||||
|
void processPreloadConfig(std::filesystem::path file);
|
||||||
|
void processPreloadConfigs(const Content* content);
|
||||||
|
public:
|
||||||
|
AssetsLoader(Assets* assets, const ResPaths* paths);
|
||||||
|
void addLoader(AssetType tag, aloader_func func);
|
||||||
|
|
||||||
|
/// @brief Enqueue asset load
|
||||||
|
/// @param tag asset type
|
||||||
|
/// @param filename asset file path
|
||||||
|
/// @param alias internal asset name
|
||||||
|
/// @param settings asset loading settings (based on asset type)
|
||||||
|
void add(
|
||||||
|
AssetType tag,
|
||||||
|
const std::string filename,
|
||||||
|
const std::string alias,
|
||||||
|
std::shared_ptr<AssetCfg> settings=nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
bool hasNext() const;
|
||||||
|
bool loadNext();
|
||||||
|
|
||||||
|
std::shared_ptr<Task> startTask(runnable onDone);
|
||||||
|
|
||||||
|
const ResPaths* getPaths() const;
|
||||||
|
aloader_func getLoader(AssetType tag);
|
||||||
|
|
||||||
|
/// @brief Enqueue core and content assets
|
||||||
|
/// @param loader target loader
|
||||||
|
/// @param content engine content
|
||||||
|
static void addDefaults(AssetsLoader& loader, const Content* content);
|
||||||
|
|
||||||
|
static bool loadExternalTexture(
|
||||||
|
Assets* assets,
|
||||||
|
const std::string& name,
|
||||||
|
std::vector<std::filesystem::path> alternatives
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ASSETS_ASSETS_LOADER_HPP_
|
||||||
@@ -1,55 +1,54 @@
|
|||||||
#include "assetload_funcs.h"
|
#include "assetload_funcs.hpp"
|
||||||
|
|
||||||
|
#include "Assets.hpp"
|
||||||
|
#include "AssetsLoader.hpp"
|
||||||
|
#include "../data/dynamic.hpp"
|
||||||
|
#include "../audio/audio.hpp"
|
||||||
|
#include "../files/files.hpp"
|
||||||
|
#include "../files/engine_paths.hpp"
|
||||||
|
#include "../coders/imageio.hpp"
|
||||||
|
#include "../coders/json.hpp"
|
||||||
|
#include "../coders/GLSLExtension.hpp"
|
||||||
|
#include "../graphics/core/Shader.hpp"
|
||||||
|
#include "../graphics/core/Texture.hpp"
|
||||||
|
#include "../graphics/core/ImageData.hpp"
|
||||||
|
#include "../graphics/core/Atlas.hpp"
|
||||||
|
#include "../graphics/core/Font.hpp"
|
||||||
|
#include "../graphics/core/TextureAnimation.hpp"
|
||||||
|
#include "../frontend/UiDocument.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include "Assets.h"
|
|
||||||
#include "AssetsLoader.h"
|
|
||||||
#include "../audio/audio.h"
|
|
||||||
#include "../files/files.h"
|
|
||||||
#include "../files/engine_paths.h"
|
|
||||||
#include "../coders/png.h"
|
|
||||||
#include "../coders/json.h"
|
|
||||||
#include "../graphics/Shader.h"
|
|
||||||
#include "../graphics/Texture.h"
|
|
||||||
#include "../graphics/ImageData.h"
|
|
||||||
#include "../graphics/Atlas.h"
|
|
||||||
#include "../graphics/Font.h"
|
|
||||||
#include "../graphics/TextureAnimation.h"
|
|
||||||
#include "../frontend/UiDocument.h"
|
|
||||||
#include "../logic/scripting/scripting.h"
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static bool animation(
|
static bool animation(
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string directory,
|
const std::string& atlasName,
|
||||||
const std::string name,
|
const std::string& directory,
|
||||||
|
const std::string& name,
|
||||||
Atlas* dstAtlas
|
Atlas* dstAtlas
|
||||||
);
|
);
|
||||||
|
|
||||||
bool assetload::texture(
|
assetload::postfunc assetload::texture(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets* assets,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string filename,
|
const std::string filename,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg>
|
std::shared_ptr<AssetCfg>
|
||||||
) {
|
) {
|
||||||
std::unique_ptr<Texture> texture(
|
std::shared_ptr<ImageData> image (
|
||||||
png::load_texture(paths->find(filename+".png").u8string())
|
imageio::read(paths->find(filename+".png").u8string()).release()
|
||||||
);
|
);
|
||||||
if (texture == nullptr) {
|
return [name, image](auto assets) {
|
||||||
std::cerr << "failed to load texture '" << name << "'" << std::endl;
|
assets->store(Texture::from(image.get()).release(), name);
|
||||||
return false;
|
};
|
||||||
}
|
|
||||||
assets->store(texture.release(), name);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::shader(
|
assetload::postfunc assetload::shader(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets* assets,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string filename,
|
const std::string filename,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
@@ -61,43 +60,32 @@ bool assetload::shader(
|
|||||||
std::string vertexSource = files::read_string(vertexFile);
|
std::string vertexSource = files::read_string(vertexFile);
|
||||||
std::string fragmentSource = files::read_string(fragmentFile);
|
std::string fragmentSource = files::read_string(fragmentFile);
|
||||||
|
|
||||||
Shader* shader = Shader::create(
|
vertexSource = Shader::preprocessor->process(vertexFile, vertexSource);
|
||||||
vertexFile.string(),
|
fragmentSource = Shader::preprocessor->process(fragmentFile, fragmentSource);
|
||||||
fragmentFile.string(),
|
|
||||||
vertexSource, fragmentSource
|
|
||||||
);
|
|
||||||
|
|
||||||
if (shader == nullptr) {
|
return [=](auto assets) {
|
||||||
std::cerr << "failed to load shader '" << name << "'" << std::endl;
|
assets->store(Shader::create(
|
||||||
return false;
|
vertexFile.u8string(),
|
||||||
}
|
fragmentFile.u8string(),
|
||||||
assets->store(shader, name);
|
vertexSource, fragmentSource
|
||||||
return true;
|
), name);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) {
|
static bool append_atlas(AtlasBuilder& atlas, const fs::path& file) {
|
||||||
// png is only supported format
|
|
||||||
if (file.extension() != ".png")
|
|
||||||
return false;
|
|
||||||
std::string name = file.stem().string();
|
std::string name = file.stem().string();
|
||||||
// skip duplicates
|
// skip duplicates
|
||||||
if (atlas.has(name)) {
|
if (atlas.has(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::unique_ptr<ImageData> image(png::load_image(file.string()));
|
auto image = imageio::read(file.string());
|
||||||
if (image == nullptr) {
|
|
||||||
std::cerr << "could not to load " << file.string() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
image->fixAlphaColor();
|
image->fixAlphaColor();
|
||||||
atlas.add(name, image.release());
|
atlas.add(name, std::move(image));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::atlas(
|
assetload::postfunc assetload::atlas(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets* assets,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string directory,
|
const std::string directory,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
@@ -105,201 +93,219 @@ bool assetload::atlas(
|
|||||||
) {
|
) {
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
for (const auto& file : paths->listdir(directory)) {
|
for (const auto& file : paths->listdir(directory)) {
|
||||||
if (!appendAtlas(builder, file)) continue;
|
if (!imageio::is_read_supported(file.extension().u8string()))
|
||||||
|
continue;
|
||||||
|
if (!append_atlas(builder, file))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
Atlas* atlas = builder.build(2);
|
std::set<std::string> names = builder.getNames();
|
||||||
assets->store(atlas, name);
|
Atlas* atlas = builder.build(2, false).release();
|
||||||
for (const auto& file : builder.getNames()) {
|
return [=](auto assets) {
|
||||||
animation(assets, paths, "textures", file, atlas);
|
atlas->prepare();
|
||||||
}
|
assets->store(atlas, name);
|
||||||
return true;
|
for (const auto& file : names) {
|
||||||
|
animation(assets, paths, name, directory, file, atlas);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::font(
|
assetload::postfunc assetload::font(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets* assets,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string filename,
|
const std::string filename,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg>
|
std::shared_ptr<AssetCfg>
|
||||||
) {
|
) {
|
||||||
std::vector<std::unique_ptr<Texture>> pages;
|
auto pages = std::make_shared<std::vector<std::unique_ptr<ImageData>>>();
|
||||||
for (size_t i = 0; i <= 4; i++) {
|
for (size_t i = 0; i <= 4; i++) {
|
||||||
std::string name = filename + "_" + std::to_string(i) + ".png";
|
std::string name = filename + "_" + std::to_string(i) + ".png";
|
||||||
name = paths->find(name).string();
|
name = paths->find(name).string();
|
||||||
std::unique_ptr<Texture> texture (png::load_texture(name));
|
pages->push_back(imageio::read(name));
|
||||||
if (texture == nullptr) {
|
|
||||||
std::cerr << "failed to load bitmap font '" << name;
|
|
||||||
std::cerr << "' (missing page " << std::to_string(i) << ")";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pages.push_back(std::move(texture));
|
|
||||||
}
|
}
|
||||||
int res = pages[0]->getHeight() / 16;
|
return [=](auto assets) {
|
||||||
assets->store(new Font(std::move(pages), res, 4), name);
|
int res = pages->at(0)->getHeight() / 16;
|
||||||
return true;
|
std::vector<std::unique_ptr<Texture>> textures;
|
||||||
|
for (auto& page : *pages) {
|
||||||
|
textures.emplace_back(Texture::from(page.get()));
|
||||||
|
}
|
||||||
|
assets->store(new Font(std::move(textures), res, 4), name);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assetload::layout(
|
assetload::postfunc assetload::layout(
|
||||||
AssetsLoader& loader,
|
AssetsLoader*,
|
||||||
Assets* assets,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string file,
|
const std::string file,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> config
|
std::shared_ptr<AssetCfg> config
|
||||||
) {
|
) {
|
||||||
try {
|
return [=](auto assets) {
|
||||||
auto cfg = dynamic_cast<LayoutCfg*>(config.get());
|
try {
|
||||||
auto document = UiDocument::read(loader, cfg->env, name, file);
|
auto cfg = std::dynamic_pointer_cast<LayoutCfg>(config);
|
||||||
assets->store(document.release(), name);
|
auto document = UiDocument::read(cfg->env, name, file);
|
||||||
return true;
|
assets->store(document.release(), name);
|
||||||
} catch (const parsing_error& err) {
|
} catch (const parsing_error& err) {
|
||||||
std::cerr << "failed to parse layout XML '" << file << "'" << std::endl;
|
throw std::runtime_error(
|
||||||
std::cerr << err.errorLog() << std::endl;
|
"failed to parse layout XML '"+file+"':\n"+err.errorLog()
|
||||||
return false;
|
);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
bool assetload::sound(
|
assetload::postfunc assetload::sound(
|
||||||
AssetsLoader& loader,
|
AssetsLoader*,
|
||||||
Assets* assets,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string file,
|
const std::string file,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> config
|
std::shared_ptr<AssetCfg> config
|
||||||
) {
|
) {
|
||||||
auto cfg = dynamic_cast<SoundCfg*>(config.get());
|
auto cfg = std::dynamic_pointer_cast<SoundCfg>(config);
|
||||||
bool keepPCM = cfg ? cfg->keepPCM : false;
|
bool keepPCM = cfg ? cfg->keepPCM : false;
|
||||||
|
|
||||||
std::string extension = ".ogg";
|
std::string extension = ".ogg";
|
||||||
try {
|
std::unique_ptr<audio::Sound> baseSound = nullptr;
|
||||||
std::unique_ptr<audio::Sound> baseSound = nullptr;
|
|
||||||
|
|
||||||
// looking for 'sound_name' as base sound
|
// looking for 'sound_name' as base sound
|
||||||
auto soundFile = paths->find(file+extension);
|
auto soundFile = paths->find(file+extension);
|
||||||
if (fs::exists(soundFile)) {
|
if (fs::exists(soundFile)) {
|
||||||
baseSound.reset(audio::load_sound(soundFile, keepPCM));
|
baseSound.reset(audio::load_sound(soundFile, keepPCM));
|
||||||
}
|
|
||||||
// looking for 'sound_name_0' as base sound
|
|
||||||
auto variantFile = paths->find(file+"_0"+extension);
|
|
||||||
if (fs::exists(variantFile)) {
|
|
||||||
baseSound.reset(audio::load_sound(variantFile, keepPCM));
|
|
||||||
}
|
|
||||||
|
|
||||||
// loading sound variants
|
|
||||||
for (uint i = 1; ; i++) {
|
|
||||||
auto variantFile = paths->find(file+"_"+std::to_string(i)+extension);
|
|
||||||
if (!fs::exists(variantFile)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
|
|
||||||
}
|
|
||||||
assets->store(baseSound.release(), name);
|
|
||||||
}
|
|
||||||
catch (std::runtime_error& err) {
|
|
||||||
std::cerr << err.what() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
// looking for 'sound_name_0' as base sound
|
||||||
|
auto variantFile = paths->find(file+"_0"+extension);
|
||||||
|
if (fs::exists(variantFile)) {
|
||||||
|
baseSound.reset(audio::load_sound(variantFile, keepPCM));
|
||||||
|
}
|
||||||
|
|
||||||
|
// loading sound variants
|
||||||
|
for (uint i = 1; ; i++) {
|
||||||
|
auto variantFile = paths->find(file+"_"+std::to_string(i)+extension);
|
||||||
|
if (!fs::exists(variantFile)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
baseSound->variants.emplace_back(audio::load_sound(variantFile, keepPCM));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseSound == nullptr) {
|
||||||
|
throw std::runtime_error("could not to find sound: " + file);
|
||||||
|
}
|
||||||
|
auto sound = baseSound.release();
|
||||||
|
return [=](auto assets) {
|
||||||
|
assets->store(sound, name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_anim_file(
|
||||||
|
const std::string& animFile,
|
||||||
|
std::vector<std::pair<std::string, int>>& frameList
|
||||||
|
) {
|
||||||
|
auto root = files::read_json(animFile);
|
||||||
|
auto frameArr = root->list("frames");
|
||||||
|
float frameDuration = DEFAULT_FRAME_DURATION;
|
||||||
|
std::string frameName;
|
||||||
|
|
||||||
|
if (frameArr) {
|
||||||
|
for (size_t i = 0; i < frameArr->size(); i++) {
|
||||||
|
auto currentFrame = frameArr->list(i);
|
||||||
|
|
||||||
|
frameName = currentFrame->str(0);
|
||||||
|
if (currentFrame->size() > 1) {
|
||||||
|
frameDuration = currentFrame->integer(1);
|
||||||
|
}
|
||||||
|
frameList.emplace_back(frameName, frameDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextureAnimation create_animation(
|
||||||
|
Atlas* srcAtlas,
|
||||||
|
Atlas* dstAtlas,
|
||||||
|
const std::string& name,
|
||||||
|
const std::set<std::string>& frameNames,
|
||||||
|
const std::vector<std::pair<std::string, int>>& frameList
|
||||||
|
) {
|
||||||
|
Texture* srcTex = srcAtlas->getTexture();
|
||||||
|
Texture* dstTex = dstAtlas->getTexture();
|
||||||
|
UVRegion region = dstAtlas->get(name);
|
||||||
|
|
||||||
|
TextureAnimation animation(srcTex, dstTex);
|
||||||
|
Frame frame;
|
||||||
|
|
||||||
|
uint dstWidth = dstTex->getWidth();
|
||||||
|
uint dstHeight = dstTex->getHeight();
|
||||||
|
|
||||||
|
uint srcWidth = srcTex->getWidth();
|
||||||
|
uint srcHeight = srcTex->getHeight();
|
||||||
|
|
||||||
|
frame.dstPos = glm::ivec2(region.u1 * dstWidth, region.v1 * dstHeight);
|
||||||
|
frame.size = glm::ivec2(region.u2 * dstWidth, region.v2 * dstHeight) - frame.dstPos;
|
||||||
|
|
||||||
|
for (const auto& elem : frameList) {
|
||||||
|
if (!srcAtlas->has(elem.first)) {
|
||||||
|
std::cerr << "Unknown frame name: " << elem.first << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
region = srcAtlas->get(elem.first);
|
||||||
|
if (elem.second > 0) {
|
||||||
|
frame.duration = static_cast<float>(elem.second) / 1000.0f;
|
||||||
|
}
|
||||||
|
frame.srcPos = glm::ivec2(region.u1 * srcWidth, srcHeight - region.v2 * srcHeight);
|
||||||
|
animation.addFrame(frame);
|
||||||
|
}
|
||||||
|
return animation;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool contains(
|
||||||
|
const std::vector<std::pair<std::string, int>>& frameList,
|
||||||
|
const std::string& frameName
|
||||||
|
) {
|
||||||
|
for (const auto& elem : frameList) {
|
||||||
|
if (frameName == elem.first) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool animation(
|
static bool animation(
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string directory,
|
const std::string& atlasName,
|
||||||
const std::string name,
|
const std::string& directory,
|
||||||
|
const std::string& name,
|
||||||
Atlas* dstAtlas
|
Atlas* dstAtlas
|
||||||
) {
|
) {
|
||||||
std::string animsDir = directory + "/animations";
|
std::string animsDir = directory + "/animation";
|
||||||
std::string blocksDir = directory + "/blocks";
|
|
||||||
|
|
||||||
for (const auto& folder : paths->listdir(animsDir)) {
|
for (const auto& folder : paths->listdir(animsDir)) {
|
||||||
if (!fs::is_directory(folder)) continue;
|
if (!fs::is_directory(folder)) continue;
|
||||||
if (folder.filename().string() != name) continue;
|
if (folder.filename().u8string() != name) continue;
|
||||||
if (fs::is_empty(folder)) continue;
|
if (fs::is_empty(folder)) continue;
|
||||||
|
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
appendAtlas(builder, paths->find(blocksDir + "/" + name + ".png"));
|
append_atlas(builder, paths->find(directory + "/" + name + ".png"));
|
||||||
|
|
||||||
std::string animFile = folder.string() + "/animation.json";
|
|
||||||
|
|
||||||
std::vector<std::pair<std::string, float>> frameList;
|
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, int>> frameList;
|
||||||
|
std::string animFile = folder.u8string() + "/animation.json";
|
||||||
if (fs::exists(animFile)) {
|
if (fs::exists(animFile)) {
|
||||||
auto root = files::read_json(animFile);
|
read_anim_file(animFile, frameList);
|
||||||
|
|
||||||
auto frameArr = root->list("frames");
|
|
||||||
|
|
||||||
float frameDuration = DEFAULT_FRAME_DURATION;
|
|
||||||
std::string frameName;
|
|
||||||
|
|
||||||
if (frameArr) {
|
|
||||||
for (size_t i = 0; i < frameArr->size(); i++) {
|
|
||||||
auto currentFrame = frameArr->list(i);
|
|
||||||
|
|
||||||
frameName = currentFrame->str(0);
|
|
||||||
if (currentFrame->size() > 1)
|
|
||||||
frameDuration = static_cast<float>(currentFrame->integer(1)) / 1000;
|
|
||||||
|
|
||||||
frameList.emplace_back(frameName, frameDuration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (const auto& file : paths->listdir(animsDir + "/" + name)) {
|
for (const auto& file : paths->listdir(animsDir + "/" + name)) {
|
||||||
if (!frameList.empty()) {
|
if (!frameList.empty() && !contains(frameList, file.stem().u8string())) {
|
||||||
bool contains = false;
|
continue;
|
||||||
for (const auto& elem : frameList) {
|
|
||||||
if (file.stem() == elem.first) {
|
|
||||||
contains = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!contains) continue;
|
|
||||||
}
|
}
|
||||||
if (!appendAtlas(builder, file)) continue;
|
if (!append_atlas(builder, file))
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
auto srcAtlas = builder.build(2, true);
|
||||||
std::unique_ptr<Atlas> srcAtlas (builder.build(2));
|
|
||||||
|
|
||||||
Texture* srcTex = srcAtlas->getTexture();
|
|
||||||
Texture* dstTex = dstAtlas->getTexture();
|
|
||||||
|
|
||||||
TextureAnimation animation(srcTex, dstTex);
|
|
||||||
Frame frame;
|
|
||||||
UVRegion region = dstAtlas->get(name);
|
|
||||||
|
|
||||||
uint dstWidth = dstTex->getWidth();
|
|
||||||
uint dstHeight = dstTex->getHeight();
|
|
||||||
|
|
||||||
uint srcWidth = srcTex->getWidth();
|
|
||||||
uint srcHeight = srcTex->getHeight();
|
|
||||||
|
|
||||||
frame.dstPos = glm::ivec2(region.u1 * dstWidth, region.v1 * dstHeight);
|
|
||||||
frame.size = glm::ivec2(region.u2 * dstWidth, region.v2 * dstHeight) - frame.dstPos;
|
|
||||||
|
|
||||||
if (frameList.empty()) {
|
if (frameList.empty()) {
|
||||||
for (const auto& elem : builder.getNames()) {
|
for (const auto& frameName : builder.getNames()) {
|
||||||
region = srcAtlas->get(elem);
|
frameList.emplace_back(frameName, 0);
|
||||||
frame.srcPos = glm::ivec2(region.u1 * srcWidth, srcHeight - region.v2 * srcHeight);
|
|
||||||
animation.addFrame(frame);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
auto animation = create_animation(
|
||||||
for (const auto& elem : frameList) {
|
srcAtlas.get(), dstAtlas, name, builder.getNames(), frameList
|
||||||
if (!srcAtlas->has(elem.first)) {
|
);
|
||||||
std::cerr << "Unknown frame name: " << elem.first << std::endl;
|
assets->store(srcAtlas.release(), atlasName + "/" + name + "_animation");
|
||||||
continue;
|
|
||||||
}
|
|
||||||
region = srcAtlas->get(elem.first);
|
|
||||||
frame.duration = elem.second;
|
|
||||||
frame.srcPos = glm::ivec2(region.u1 * srcWidth, srcHeight - region.v2 * srcHeight);
|
|
||||||
animation.addFrame(frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assets->store(srcAtlas.release(), name + "_animation");
|
|
||||||
assets->store(animation);
|
assets->store(animation);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#ifndef ASSETS_ASSET_LOADERS_H_
|
#ifndef ASSETS_ASSET_LOADERS_HPP_
|
||||||
#define ASSETS_ASSET_LOADERS_H_
|
#define ASSETS_ASSET_LOADERS_HPP_
|
||||||
|
|
||||||
|
#include "Assets.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -12,50 +14,44 @@ struct AssetCfg;
|
|||||||
|
|
||||||
/// @brief see AssetsLoader.h: aloader_func
|
/// @brief see AssetsLoader.h: aloader_func
|
||||||
namespace assetload {
|
namespace assetload {
|
||||||
bool texture(
|
postfunc texture(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets*,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string filename,
|
const std::string filename,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool shader(
|
postfunc shader(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets*,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string filename,
|
const std::string filename,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool atlas(
|
postfunc atlas(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets*,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string directory,
|
const std::string directory,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool font(
|
postfunc font(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets*,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string filename,
|
const std::string filename,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
bool layout(
|
postfunc layout(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets*,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string file,
|
const std::string file,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
std::shared_ptr<AssetCfg> settings
|
std::shared_ptr<AssetCfg> settings
|
||||||
);
|
);
|
||||||
|
|
||||||
bool sound(
|
postfunc sound(
|
||||||
AssetsLoader&,
|
AssetsLoader*,
|
||||||
Assets*,
|
|
||||||
const ResPaths* paths,
|
const ResPaths* paths,
|
||||||
const std::string file,
|
const std::string file,
|
||||||
const std::string name,
|
const std::string name,
|
||||||
@@ -63,4 +59,4 @@ namespace assetload {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ASSETS_ASSET_LOADERS_H_
|
#endif // ASSETS_ASSET_LOADERS_HPP_
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
#include "ALAudio.h"
|
#include "ALAudio.hpp"
|
||||||
#include "alutil.h"
|
|
||||||
|
#include "alutil.hpp"
|
||||||
|
#include "../../debug/Logger.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
static debug::Logger logger("al-audio");
|
||||||
|
|
||||||
using namespace audio;
|
using namespace audio;
|
||||||
|
|
||||||
ALSound::ALSound(ALAudio* al, uint buffer, std::shared_ptr<PCM> pcm, bool keepPCM)
|
ALSound::ALSound(ALAudio* al, uint buffer, std::shared_ptr<PCM> pcm, bool keepPCM)
|
||||||
@@ -203,10 +208,10 @@ ALSpeaker::~ALSpeaker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALSpeaker::update(const Channel* channel, float masterVolume) {
|
void ALSpeaker::update(const Channel* channel) {
|
||||||
if (source == 0)
|
if (source == 0)
|
||||||
return;
|
return;
|
||||||
float gain = this->volume * channel->getVolume()*masterVolume;
|
float gain = this->volume * channel->getVolume();
|
||||||
AL_CHECK(alSourcef(source, AL_GAIN, gain));
|
AL_CHECK(alSourcef(source, AL_GAIN, gain));
|
||||||
|
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
@@ -341,14 +346,14 @@ ALAudio::ALAudio(ALCdevice* device, ALCcontext* context)
|
|||||||
alcGetIntegerv(device, ALC_ALL_ATTRIBUTES, size, &attrs[0]);
|
alcGetIntegerv(device, ALC_ALL_ATTRIBUTES, size, &attrs[0]);
|
||||||
for (size_t i = 0; i < attrs.size(); ++i){
|
for (size_t i = 0; i < attrs.size(); ++i){
|
||||||
if (attrs[i] == ALC_MONO_SOURCES) {
|
if (attrs[i] == ALC_MONO_SOURCES) {
|
||||||
std::cout << "AL: max mono sources: " << attrs[i+1] << std::endl;
|
logger.info() << "max mono sources: " << attrs[i+1];
|
||||||
maxSources = attrs[i+1];
|
maxSources = attrs[i+1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto devices = getAvailableDevices();
|
auto devices = getAvailableDevices();
|
||||||
std::cout << "AL devices:" << std::endl;
|
logger.info() << "devices:";
|
||||||
for (auto& name : devices) {
|
for (auto& name : devices) {
|
||||||
std::cout << " " << name << std::endl;
|
logger.info() << " " << name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,7 +373,7 @@ ALAudio::~ALAudio() {
|
|||||||
AL_CHECK(alcMakeContextCurrent(context));
|
AL_CHECK(alcMakeContextCurrent(context));
|
||||||
alcDestroyContext(context);
|
alcDestroyContext(context);
|
||||||
if (!alcCloseDevice(device)) {
|
if (!alcCloseDevice(device)) {
|
||||||
std::cerr << "AL: device not closed!" << std::endl;
|
logger.error() << "device not closed!";
|
||||||
}
|
}
|
||||||
device = nullptr;
|
device = nullptr;
|
||||||
context = nullptr;
|
context = nullptr;
|
||||||
@@ -395,7 +400,7 @@ ALAudio* ALAudio::create() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
AL_CHECK();
|
AL_CHECK();
|
||||||
std::cout << "AL: initialized" << std::endl;
|
logger.info() << "initialized";
|
||||||
return new ALAudio(device, context);
|
return new ALAudio(device, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +411,7 @@ uint ALAudio::getFreeSource(){
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
if (allsources.size() == maxSources){
|
if (allsources.size() == maxSources){
|
||||||
std::cerr << "attempted to create new source, but limit is " << maxSources << std::endl;
|
logger.error() << "attempted to create new source, but limit is " << maxSources;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ALuint id;
|
ALuint id;
|
||||||
@@ -467,6 +472,7 @@ void ALAudio::setListener(glm::vec3 position, glm::vec3 velocity, glm::vec3 at,
|
|||||||
AL_CHECK(alListener3f(AL_POSITION, position.x, position.y, position.z));
|
AL_CHECK(alListener3f(AL_POSITION, position.x, position.y, position.z));
|
||||||
AL_CHECK(alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z));
|
AL_CHECK(alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z));
|
||||||
AL_CHECK(alListenerfv(AL_ORIENTATION, listenerOri));
|
AL_CHECK(alListenerfv(AL_ORIENTATION, listenerOri));
|
||||||
|
AL_CHECK(alListenerf(AL_GAIN, get_channel(0)->getVolume()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALAudio::update(double delta) {
|
void ALAudio::update(double delta) {
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#ifndef SRC_AUDIO_AUDIO_H_
|
#ifndef SRC_AUDIO_AUDIO_HPP_
|
||||||
#define SRC_AUDIO_AUDIO_H_
|
#define SRC_AUDIO_AUDIO_HPP_
|
||||||
|
|
||||||
|
#include "../audio.hpp"
|
||||||
|
#include "../../typedefs.hpp"
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -15,9 +18,6 @@
|
|||||||
#include <AL/alc.h>
|
#include <AL/alc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../audio.h"
|
|
||||||
#include "../../typedefs.h"
|
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
struct ALBuffer;
|
struct ALBuffer;
|
||||||
class ALAudio;
|
class ALAudio;
|
||||||
@@ -91,7 +91,7 @@ namespace audio {
|
|||||||
ALSpeaker(ALAudio* al, uint source, int priority, int channel);
|
ALSpeaker(ALAudio* al, uint source, int priority, int channel);
|
||||||
~ALSpeaker();
|
~ALSpeaker();
|
||||||
|
|
||||||
void update(const Channel* channel, float masterVolume) override;
|
void update(const Channel* channel) override;
|
||||||
int getChannel() const override;
|
int getChannel() const override;
|
||||||
|
|
||||||
State getState() const override;
|
State getState() const override;
|
||||||
@@ -168,4 +168,4 @@ namespace audio {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SRC_AUDIO_AUDIO_H_ */
|
#endif // SRC_AUDIO_AUDIO_HPP_
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "alutil.h"
|
#include "alutil.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#ifndef SRC_AUDIO_AUDIOUTIL_H_
|
#ifndef AUDIO_AUDIOUTIL_HPP_
|
||||||
#define SRC_AUDIO_AUDIOUTIL_H_
|
#define AUDIO_AUDIOUTIL_HPP_
|
||||||
|
|
||||||
|
#include "../../typedefs.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -12,7 +14,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include "../../typedefs.h"
|
|
||||||
|
|
||||||
#define AL_CHECK(STATEMENT) STATEMENT; AL::check_errors(__FILE__, __LINE__)
|
#define AL_CHECK(STATEMENT) STATEMENT; AL::check_errors(__FILE__, __LINE__)
|
||||||
#define AL_GET_ERROR() AL::check_errors(__FILE__, __LINE__)
|
#define AL_GET_ERROR() AL::check_errors(__FILE__, __LINE__)
|
||||||
@@ -80,4 +81,4 @@ namespace AL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SRC_AUDIO_AUDIOUTIL_H_ */
|
#endif // AUDIO_AUDIOUTIL_HPP_
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "NoAudio.h"
|
#include "NoAudio.hpp"
|
||||||
|
|
||||||
using namespace audio;
|
using namespace audio;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef AUDIO_NOAUDIO_H_
|
#ifndef AUDIO_NOAUDIO_HPP_
|
||||||
#define AUDIO_NOAUDIO_H_
|
#define AUDIO_NOAUDIO_HPP_
|
||||||
|
|
||||||
#include "audio.h"
|
#include "audio.hpp"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
class NoSound : public Sound {
|
class NoSound : public Sound {
|
||||||
@@ -85,4 +85,4 @@ namespace audio {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // AUDIO_NOAUDIO_H_
|
#endif // AUDIO_NOAUDIO_HPP_
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
#include "audio.h"
|
#include "audio.hpp"
|
||||||
|
|
||||||
|
#include "NoAudio.hpp"
|
||||||
|
#include "AL/ALAudio.hpp"
|
||||||
|
|
||||||
|
#include "../coders/wav.hpp"
|
||||||
|
#include "../coders/ogg.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "NoAudio.h"
|
|
||||||
#include "AL/ALAudio.h"
|
|
||||||
|
|
||||||
#include "../coders/wav.h"
|
|
||||||
#include "../coders/ogg.h"
|
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
static speakerid_t nextId = 1;
|
static speakerid_t nextId = 1;
|
||||||
static Backend* backend;
|
static Backend* backend;
|
||||||
@@ -383,13 +383,12 @@ void audio::update(double delta) {
|
|||||||
entry.second->update(delta);
|
entry.second->update(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
float masterVolume = channels.at(0)->getVolume();
|
|
||||||
for (auto it = speakers.begin(); it != speakers.end();) {
|
for (auto it = speakers.begin(); it != speakers.end();) {
|
||||||
auto speaker = it->second.get();
|
auto speaker = it->second.get();
|
||||||
int speakerChannel = speaker->getChannel();
|
int speakerChannel = speaker->getChannel();
|
||||||
auto channel = get_channel(speakerChannel);
|
auto channel = get_channel(speakerChannel);
|
||||||
if (channel != nullptr) {
|
if (channel != nullptr) {
|
||||||
speaker->update(channel, speakerChannel == 0 ? 1.0f : masterVolume);
|
speaker->update(channel);
|
||||||
}
|
}
|
||||||
if (speaker->isStopped()) {
|
if (speaker->isStopped()) {
|
||||||
streams.erase(it->first);
|
streams.erase(it->first);
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#ifndef AUDIO_AUDIO_H_
|
#ifndef AUDIO_AUDIO_HPP_
|
||||||
#define AUDIO_AUDIO_H_
|
#define AUDIO_AUDIO_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
@@ -235,8 +236,7 @@ namespace audio {
|
|||||||
|
|
||||||
/// @brief Synchronize the speaker with channel settings
|
/// @brief Synchronize the speaker with channel settings
|
||||||
/// @param channel speaker channel
|
/// @param channel speaker channel
|
||||||
/// @param masterVolume volume of the master channel
|
virtual void update(const Channel* channel) = 0;
|
||||||
virtual void update(const Channel* channel, float masterVolume) = 0;
|
|
||||||
|
|
||||||
/// @brief Check speaker channel index
|
/// @brief Check speaker channel index
|
||||||
virtual int getChannel() const = 0;
|
virtual int getChannel() const = 0;
|
||||||
@@ -353,52 +353,52 @@ namespace audio {
|
|||||||
|
|
||||||
/// @brief Initialize audio system or use no audio mode
|
/// @brief Initialize audio system or use no audio mode
|
||||||
/// @param enabled try to initialize actual audio
|
/// @param enabled try to initialize actual audio
|
||||||
extern void initialize(bool enabled);
|
void initialize(bool enabled);
|
||||||
|
|
||||||
/// @brief Load audio file info and PCM data
|
/// @brief Load audio file info and PCM data
|
||||||
/// @param file audio file
|
/// @param file audio file
|
||||||
/// @param headerOnly read header only
|
/// @param headerOnly read header only
|
||||||
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
||||||
/// @return PCM audio data
|
/// @return PCM audio data
|
||||||
extern PCM* load_PCM(const fs::path& file, bool headerOnly);
|
PCM* load_PCM(const fs::path& file, bool headerOnly);
|
||||||
|
|
||||||
/// @brief Load sound from file
|
/// @brief Load sound from file
|
||||||
/// @param file audio file path
|
/// @param file audio file path
|
||||||
/// @param keepPCM store PCM data in sound to make it accessible with Sound::getPCM
|
/// @param keepPCM store PCM data in sound to make it accessible with Sound::getPCM
|
||||||
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
||||||
/// @return new Sound instance
|
/// @return new Sound instance
|
||||||
extern Sound* load_sound(const fs::path& file, bool keepPCM);
|
Sound* load_sound(const fs::path& file, bool keepPCM);
|
||||||
|
|
||||||
/// @brief Create new sound from PCM data
|
/// @brief Create new sound from PCM data
|
||||||
/// @param pcm PCM data
|
/// @param pcm PCM data
|
||||||
/// @param keepPCM store PCM data in sound to make it accessible with Sound::getPCM
|
/// @param keepPCM store PCM data in sound to make it accessible with Sound::getPCM
|
||||||
/// @return new Sound instance
|
/// @return new Sound instance
|
||||||
extern Sound* create_sound(std::shared_ptr<PCM> pcm, bool keepPCM);
|
Sound* create_sound(std::shared_ptr<PCM> pcm, bool keepPCM);
|
||||||
|
|
||||||
/// @brief Open new PCM stream from file
|
/// @brief Open new PCM stream from file
|
||||||
/// @param file audio file path
|
/// @param file audio file path
|
||||||
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
/// @throws std::runtime_error if I/O error ocurred or format is unknown
|
||||||
/// @return new PCMStream instance
|
/// @return new PCMStream instance
|
||||||
extern PCMStream* open_PCM_stream(const fs::path& file);
|
PCMStream* open_PCM_stream(const fs::path& file);
|
||||||
|
|
||||||
/// @brief Open new audio stream from file
|
/// @brief Open new audio stream from file
|
||||||
/// @param file audio file path
|
/// @param file audio file path
|
||||||
/// @param keepSource store PCMStream in stream to make it accessible with Stream::getSource
|
/// @param keepSource store PCMStream in stream to make it accessible with Stream::getSource
|
||||||
/// @return new Stream instance
|
/// @return new Stream instance
|
||||||
extern Stream* open_stream(const fs::path& file, bool keepSource);
|
Stream* open_stream(const fs::path& file, bool keepSource);
|
||||||
|
|
||||||
/// @brief Open new audio stream from source
|
/// @brief Open new audio stream from source
|
||||||
/// @param stream PCM data source
|
/// @param stream PCM data source
|
||||||
/// @param keepSource store PCMStream in stream to make it accessible with Stream::getSource
|
/// @param keepSource store PCMStream in stream to make it accessible with Stream::getSource
|
||||||
/// @return new Stream instance
|
/// @return new Stream instance
|
||||||
extern Stream* open_stream(std::shared_ptr<PCMStream> stream, bool keepSource);
|
Stream* open_stream(std::shared_ptr<PCMStream> stream, bool keepSource);
|
||||||
|
|
||||||
/// @brief Configure 3D listener
|
/// @brief Configure 3D listener
|
||||||
/// @param position listener position
|
/// @param position listener position
|
||||||
/// @param velocity listener velocity (used for Doppler effect)
|
/// @param velocity listener velocity (used for Doppler effect)
|
||||||
/// @param lookAt point the listener look at
|
/// @param lookAt point the listener look at
|
||||||
/// @param up camera up vector
|
/// @param up camera up vector
|
||||||
extern void set_listener(
|
void set_listener(
|
||||||
glm::vec3 position,
|
glm::vec3 position,
|
||||||
glm::vec3 velocity,
|
glm::vec3 velocity,
|
||||||
glm::vec3 lookAt,
|
glm::vec3 lookAt,
|
||||||
@@ -416,7 +416,7 @@ namespace audio {
|
|||||||
/// (PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH)
|
/// (PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH)
|
||||||
/// @param channel channel index
|
/// @param channel channel index
|
||||||
/// @return speaker id or 0
|
/// @return speaker id or 0
|
||||||
extern speakerid_t play(
|
speakerid_t play(
|
||||||
Sound* sound,
|
Sound* sound,
|
||||||
glm::vec3 position,
|
glm::vec3 position,
|
||||||
bool relative,
|
bool relative,
|
||||||
@@ -436,7 +436,7 @@ namespace audio {
|
|||||||
/// @param loop loop stream
|
/// @param loop loop stream
|
||||||
/// @param channel channel index
|
/// @param channel channel index
|
||||||
/// @return speaker id or 0
|
/// @return speaker id or 0
|
||||||
extern speakerid_t play(
|
speakerid_t play(
|
||||||
std::shared_ptr<Stream> stream,
|
std::shared_ptr<Stream> stream,
|
||||||
glm::vec3 position,
|
glm::vec3 position,
|
||||||
bool relative,
|
bool relative,
|
||||||
@@ -455,7 +455,7 @@ namespace audio {
|
|||||||
/// @param loop loop stream
|
/// @param loop loop stream
|
||||||
/// @param channel channel index
|
/// @param channel channel index
|
||||||
/// @return speaker id or 0
|
/// @return speaker id or 0
|
||||||
extern speakerid_t play_stream(
|
speakerid_t play_stream(
|
||||||
const fs::path& file,
|
const fs::path& file,
|
||||||
glm::vec3 position,
|
glm::vec3 position,
|
||||||
bool relative,
|
bool relative,
|
||||||
@@ -468,49 +468,49 @@ namespace audio {
|
|||||||
/// @brief Get speaker by id
|
/// @brief Get speaker by id
|
||||||
/// @param id speaker id
|
/// @param id speaker id
|
||||||
/// @return speaker or nullptr
|
/// @return speaker or nullptr
|
||||||
extern Speaker* get_speaker(speakerid_t id);
|
Speaker* get_speaker(speakerid_t id);
|
||||||
|
|
||||||
/// @brief Create new channel.
|
/// @brief Create new channel.
|
||||||
/// All non-builtin channels will be destroyed on audio::reset() call
|
/// All non-builtin channels will be destroyed on audio::reset() call
|
||||||
/// @param name channel name
|
/// @param name channel name
|
||||||
/// @return new channel index
|
/// @return new channel index
|
||||||
extern int create_channel(const std::string& name);
|
int create_channel(const std::string& name);
|
||||||
|
|
||||||
/// @brief Get channel index by name
|
/// @brief Get channel index by name
|
||||||
/// @param name channel name
|
/// @param name channel name
|
||||||
/// @return channel index or -1
|
/// @return channel index or -1
|
||||||
extern int get_channel_index(const std::string& name);
|
int get_channel_index(const std::string& name);
|
||||||
|
|
||||||
/// @brief Get channel by index. 0 - is master channel
|
/// @brief Get channel by index. 0 - is master channel
|
||||||
/// @param index channel index
|
/// @param index channel index
|
||||||
/// @return channel or nullptr
|
/// @return channel or nullptr
|
||||||
extern Channel* get_channel(int index);
|
Channel* get_channel(int index);
|
||||||
|
|
||||||
/// @brief Get channel by name.
|
/// @brief Get channel by name.
|
||||||
/// @param name channel name
|
/// @param name channel name
|
||||||
/// @return channel or nullptr
|
/// @return channel or nullptr
|
||||||
extern Channel* get_channel(const std::string& name);
|
Channel* get_channel(const std::string& name);
|
||||||
|
|
||||||
/// @brief Get stream associated with speaker
|
/// @brief Get stream associated with speaker
|
||||||
/// @param id speaker id
|
/// @param id speaker id
|
||||||
/// @return stream or nullptr
|
/// @return stream or nullptr
|
||||||
extern std::shared_ptr<Stream> get_associated_stream(speakerid_t id);
|
std::shared_ptr<Stream> get_associated_stream(speakerid_t id);
|
||||||
|
|
||||||
/// @brief Get alive speakers number (including paused)
|
/// @brief Get alive speakers number (including paused)
|
||||||
extern size_t count_speakers();
|
size_t count_speakers();
|
||||||
|
|
||||||
/// @brief Get playing streams number (including paused)
|
/// @brief Get playing streams number (including paused)
|
||||||
extern size_t count_streams();
|
size_t count_streams();
|
||||||
|
|
||||||
/// @brief Update audio streams and sound instanced
|
/// @brief Update audio streams and sound instanced
|
||||||
/// @param delta time elapsed since the last update (seconds)
|
/// @param delta time elapsed since the last update (seconds)
|
||||||
extern void update(double delta);
|
void update(double delta);
|
||||||
|
|
||||||
/// @brief Stop all playing audio in channel, reset channel state
|
/// @brief Stop all playing audio in channel, reset channel state
|
||||||
extern void reset_channel(int channel);
|
void reset_channel(int channel);
|
||||||
|
|
||||||
/// @brief Finalize audio system
|
/// @brief Finalize audio system
|
||||||
extern void close();
|
void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AUDIO_AUDIO_H_
|
#endif // AUDIO_AUDIO_HPP_
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#include "GLSLExtension.h"
|
#include "GLSLExtension.hpp"
|
||||||
|
|
||||||
|
#include "../util/stringutil.hpp"
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
#include "../files/files.hpp"
|
||||||
|
#include "../files/engine_paths.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "../util/stringutil.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../files/files.h"
|
|
||||||
#include "../files/engine_paths.h"
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
@@ -81,7 +83,7 @@ inline void source_line(std::stringstream& ss, uint linenum) {
|
|||||||
ss << "#line " << linenum << "\n";
|
ss << "#line " << linenum << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string GLSLExtension::process(const fs::path file, const std::string& source) {
|
const std::string GLSLExtension::process(const fs::path& file, const std::string& source) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
uint linenum = 1;
|
uint linenum = 1;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef CODERS_GLSL_EXTESION_H_
|
#ifndef CODERS_GLSL_EXTESION_HPP_
|
||||||
#define CODERS_GLSL_EXTESION_H_
|
#define CODERS_GLSL_EXTESION_HPP_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -29,7 +29,10 @@ public:
|
|||||||
bool hasHeader(const std::string& name) const;
|
bool hasHeader(const std::string& name) const;
|
||||||
bool hasDefine(const std::string& name) const;
|
bool hasDefine(const std::string& name) const;
|
||||||
|
|
||||||
const std::string process(const std::filesystem::path file, const std::string& source);
|
const std::string process(
|
||||||
|
const std::filesystem::path& file,
|
||||||
|
const std::string& source
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CODERS_GLSL_EXTESION_H_
|
#endif // CODERS_GLSL_EXTESION_HPP_
|
||||||
@@ -1,29 +1,32 @@
|
|||||||
#include "binary_json.h"
|
#include "binary_json.hpp"
|
||||||
|
|
||||||
|
#include "gzip.hpp"
|
||||||
|
#include "byte_utils.hpp"
|
||||||
|
#include "../data/dynamic.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "gzip.h"
|
|
||||||
#include "byte_utils.h"
|
|
||||||
|
|
||||||
using namespace json;
|
using namespace json;
|
||||||
using namespace dynamic;
|
using namespace dynamic;
|
||||||
|
|
||||||
static void to_binary(ByteBuilder& builder, const Value* value) {
|
static void to_binary(ByteBuilder& builder, const Value* value) {
|
||||||
switch (value->type) {
|
switch (value->type) {
|
||||||
|
case valtype::none:
|
||||||
|
throw std::runtime_error("none value is not implemented");
|
||||||
case valtype::map: {
|
case valtype::map: {
|
||||||
std::vector<ubyte> bytes = to_binary(value->value.map);
|
std::vector<ubyte> bytes = to_binary(std::get<Map*>(value->value));
|
||||||
builder.put(bytes.data(), bytes.size());
|
builder.put(bytes.data(), bytes.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case valtype::list:
|
case valtype::list:
|
||||||
builder.put(BJSON_TYPE_LIST);
|
builder.put(BJSON_TYPE_LIST);
|
||||||
for (auto& element : value->value.list->values) {
|
for (auto& element : std::get<List*>(value->value)->values) {
|
||||||
to_binary(builder, element.get());
|
to_binary(builder, element.get());
|
||||||
}
|
}
|
||||||
builder.put(BJSON_END);
|
builder.put(BJSON_END);
|
||||||
break;
|
break;
|
||||||
case valtype::integer: {
|
case valtype::integer: {
|
||||||
int64_t val = value->value.integer;
|
auto val = std::get<integer_t>(value->value);
|
||||||
if (val >= 0 && val <= 255) {
|
if (val >= 0 && val <= 255) {
|
||||||
builder.put(BJSON_TYPE_BYTE);
|
builder.put(BJSON_TYPE_BYTE);
|
||||||
builder.put(val);
|
builder.put(val);
|
||||||
@@ -41,14 +44,14 @@ static void to_binary(ByteBuilder& builder, const Value* value) {
|
|||||||
}
|
}
|
||||||
case valtype::number:
|
case valtype::number:
|
||||||
builder.put(BJSON_TYPE_NUMBER);
|
builder.put(BJSON_TYPE_NUMBER);
|
||||||
builder.putFloat64(value->value.decimal);
|
builder.putFloat64(std::get<number_t>(value->value));
|
||||||
break;
|
break;
|
||||||
case valtype::boolean:
|
case valtype::boolean:
|
||||||
builder.put(BJSON_TYPE_FALSE + value->value.boolean);
|
builder.put(BJSON_TYPE_FALSE + std::get<bool>(value->value));
|
||||||
break;
|
break;
|
||||||
case valtype::string:
|
case valtype::string:
|
||||||
builder.put(BJSON_TYPE_STRING);
|
builder.put(BJSON_TYPE_STRING);
|
||||||
builder.put(*value->value.str);
|
builder.put(std::get<std::string>(value->value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,40 +91,40 @@ static Value* value_from_binary(ByteReader& reader) {
|
|||||||
case BJSON_TYPE_DOCUMENT:
|
case BJSON_TYPE_DOCUMENT:
|
||||||
type = valtype::map;
|
type = valtype::map;
|
||||||
reader.getInt32();
|
reader.getInt32();
|
||||||
val.map = object_from_binary(reader);
|
val = object_from_binary(reader);
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_LIST:
|
case BJSON_TYPE_LIST:
|
||||||
type = valtype::list;
|
type = valtype::list;
|
||||||
val.list = array_from_binary(reader);
|
val = array_from_binary(reader);
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_BYTE:
|
case BJSON_TYPE_BYTE:
|
||||||
type = valtype::integer;
|
type = valtype::integer;
|
||||||
val.integer = reader.get();
|
val = static_cast<integer_t>(reader.get());
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_INT16:
|
case BJSON_TYPE_INT16:
|
||||||
type = valtype::integer;
|
type = valtype::integer;
|
||||||
val.integer = reader.getInt16();
|
val = static_cast<integer_t>(reader.getInt16());
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_INT32:
|
case BJSON_TYPE_INT32:
|
||||||
type = valtype::integer;
|
type = valtype::integer;
|
||||||
val.integer = reader.getInt32();
|
val = static_cast<integer_t>(reader.getInt32());
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_INT64:
|
case BJSON_TYPE_INT64:
|
||||||
type = valtype::integer;
|
type = valtype::integer;
|
||||||
val.integer = reader.getInt64();
|
val = reader.getInt64();
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_NUMBER:
|
case BJSON_TYPE_NUMBER:
|
||||||
type = valtype::number;
|
type = valtype::number;
|
||||||
val.decimal = reader.getFloat64();
|
val = reader.getFloat64();
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_FALSE:
|
case BJSON_TYPE_FALSE:
|
||||||
case BJSON_TYPE_TRUE:
|
case BJSON_TYPE_TRUE:
|
||||||
type = valtype::boolean;
|
type = valtype::boolean;
|
||||||
val.boolean = typecode - BJSON_TYPE_FALSE;
|
val = (typecode - BJSON_TYPE_FALSE) != 0;
|
||||||
break;
|
break;
|
||||||
case BJSON_TYPE_STRING:
|
case BJSON_TYPE_STRING:
|
||||||
type = valtype::string;
|
type = valtype::string;
|
||||||
val.str = new std::string(reader.getString());
|
val = reader.getString();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
@@ -166,8 +169,8 @@ std::unique_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
|
|||||||
if (value->type != valtype::map) {
|
if (value->type != valtype::map) {
|
||||||
throw std::runtime_error("root value is not an object");
|
throw std::runtime_error("root value is not an object");
|
||||||
}
|
}
|
||||||
std::unique_ptr<Map> obj (value->value.map);
|
std::unique_ptr<Map> obj (std::get<Map*>(value->value));
|
||||||
value->value.map = nullptr;
|
value->value = (Map*)nullptr;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
#ifndef CODERS_BINARY_JSON_H_
|
#ifndef CODERS_BINARY_JSON_HPP_
|
||||||
#define CODERS_BINARY_JSON_H_
|
#define CODERS_BINARY_JSON_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "../data/dynamic.h"
|
|
||||||
|
namespace dynamic {
|
||||||
|
class Map;
|
||||||
|
}
|
||||||
|
|
||||||
namespace json {
|
namespace json {
|
||||||
const int BJSON_END = 0x0;
|
const int BJSON_END = 0x0;
|
||||||
@@ -25,4 +30,4 @@ namespace json {
|
|||||||
extern std::unique_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
|
extern std::unique_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CODERS_BINARY_JSON_H_
|
#endif // CODERS_BINARY_JSON_HPP_
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "byte_utils.h"
|
#include "byte_utils.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#ifndef CODERS_BYTE_UTILS_H_
|
#ifndef CODERS_BYTE_UTILS_HPP_
|
||||||
#define CODERS_BYTE_UTILS_H_
|
#define CODERS_BYTE_UTILS_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
/* byteorder: little-endian */
|
/* byteorder: little-endian */
|
||||||
class ByteBuilder {
|
class ByteBuilder {
|
||||||
@@ -44,7 +45,7 @@ public:
|
|||||||
std::vector<ubyte> build();
|
std::vector<ubyte> build();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* byteorder: little-endian */
|
/// byteorder: little-endian
|
||||||
class ByteReader {
|
class ByteReader {
|
||||||
const ubyte* data;
|
const ubyte* data;
|
||||||
size_t size;
|
size_t size;
|
||||||
@@ -54,26 +55,29 @@ public:
|
|||||||
ByteReader(const ubyte* data);
|
ByteReader(const ubyte* data);
|
||||||
|
|
||||||
void checkMagic(const char* data, size_t size);
|
void checkMagic(const char* data, size_t size);
|
||||||
/* Read one byte (unsigned 8 bit integer) */
|
/// @brief Read one byte (unsigned 8 bit integer)
|
||||||
ubyte get();
|
ubyte get();
|
||||||
/* Read one byte (unsigned 8 bit integer) without pointer move */
|
/// @brief Read one byte (unsigned 8 bit integer) without pointer move
|
||||||
ubyte peek();
|
ubyte peek();
|
||||||
/* Read signed 16 bit integer */
|
/// @brief Read signed 16 bit integer
|
||||||
int16_t getInt16();
|
int16_t getInt16();
|
||||||
/* Read signed 32 bit integer */
|
/// @brief Read signed 32 bit integer
|
||||||
int32_t getInt32();
|
int32_t getInt32();
|
||||||
/* Read signed 64 bit integer */
|
/// @brief Read signed 64 bit integer
|
||||||
int64_t getInt64();
|
int64_t getInt64();
|
||||||
/* Read 32 bit floating-point number */
|
/// @brief Read 32 bit floating-point number
|
||||||
float getFloat32();
|
float getFloat32();
|
||||||
/* Read 64 bit floating-point number */
|
/// @brief Read 64 bit floating-point number
|
||||||
double getFloat64();
|
double getFloat64();
|
||||||
|
/// @brief Read C-String
|
||||||
const char* getCString();
|
const char* getCString();
|
||||||
|
/// @brief Read string with unsigned 32 bit number before (length)
|
||||||
std::string getString();
|
std::string getString();
|
||||||
|
/// @return true if there is at least one byte remains
|
||||||
bool hasNext() const;
|
bool hasNext() const;
|
||||||
|
|
||||||
const ubyte* pointer() const;
|
const ubyte* pointer() const;
|
||||||
void skip(size_t n);
|
void skip(size_t n);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CODERS_BYTE_UTILS_H_
|
#endif // CODERS_BYTE_UTILS_HPP_
|
||||||
@@ -1,344 +1,331 @@
|
|||||||
#include "commons.h"
|
#include "commons.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include "../util/stringutil.hpp"
|
||||||
#include <stdexcept>
|
|
||||||
#include <math.h>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
inline double power(double base, int64_t power) {
|
#include <math.h>
|
||||||
double result = 1.0;
|
|
||||||
for (int64_t i = 0; i < power; i++) {
|
inline double power(double base, int64_t power) {
|
||||||
result *= base;
|
double result = 1.0;
|
||||||
}
|
for (int64_t i = 0; i < power; i++) {
|
||||||
return result;
|
result *= base;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
parsing_error::parsing_error(
|
}
|
||||||
std::string message,
|
|
||||||
std::string filename,
|
parsing_error::parsing_error(
|
||||||
std::string source,
|
std::string message,
|
||||||
uint pos,
|
std::string filename,
|
||||||
uint line,
|
std::string source,
|
||||||
uint linestart)
|
uint pos,
|
||||||
: std::runtime_error(message), filename(filename), source(source),
|
uint line,
|
||||||
pos(pos), line(line), linestart(linestart) {
|
uint linestart)
|
||||||
}
|
: std::runtime_error(message), filename(filename), source(source),
|
||||||
|
pos(pos), line(line), linestart(linestart) {
|
||||||
std::string parsing_error::errorLog() const {
|
}
|
||||||
std::stringstream ss;
|
|
||||||
uint linepos = pos - linestart;
|
std::string parsing_error::errorLog() const {
|
||||||
ss << "parsing error in file '" << filename;
|
std::stringstream ss;
|
||||||
ss << "' at " << (line+1) << ":" << linepos << ": " << this->what() << "\n";
|
uint linepos = pos - linestart;
|
||||||
size_t end = source.find("\n", linestart);
|
ss << "parsing error in file '" << filename;
|
||||||
if (end == std::string::npos) {
|
ss << "' at " << (line+1) << ":" << linepos << ": " << this->what() << "\n";
|
||||||
end = source.length();
|
size_t end = source.find("\n", linestart);
|
||||||
}
|
if (end == std::string::npos) {
|
||||||
ss << source.substr(linestart, end-linestart) << "\n";
|
end = source.length();
|
||||||
for (uint i = 0; i < linepos; i++) {
|
}
|
||||||
ss << " ";
|
ss << source.substr(linestart, end-linestart) << "\n";
|
||||||
}
|
for (uint i = 0; i < linepos; i++) {
|
||||||
ss << "^";
|
ss << " ";
|
||||||
return ss.str();
|
}
|
||||||
|
ss << "^";
|
||||||
}
|
return ss.str();
|
||||||
|
}
|
||||||
std::string escape_string(std::string s) {
|
|
||||||
std::stringstream ss;
|
BasicParser::BasicParser(
|
||||||
ss << '"';
|
const std::string& file,
|
||||||
for (char c : s) {
|
const std::string& source
|
||||||
switch (c) {
|
) : filename(file), source(source) {
|
||||||
case '\n': ss << "\\n"; break;
|
}
|
||||||
case '\r': ss << "\\r"; break;
|
|
||||||
case '\t': ss << "\\t"; break;
|
void BasicParser::skipWhitespace() {
|
||||||
case '\f': ss << "\\f"; break;
|
while (hasNext()) {
|
||||||
case '\b': ss << "\\b"; break;
|
char next = source[pos];
|
||||||
case '"': ss << "\\\""; break;
|
if (next == '\n') {
|
||||||
case '\\': ss << "\\\\"; break;
|
line++;
|
||||||
default:
|
linestart = ++pos;
|
||||||
if (c < ' ') {
|
continue;
|
||||||
ss << "\\" << std::oct << uint(ubyte(c));
|
}
|
||||||
break;
|
if (is_whitespace(next)) {
|
||||||
}
|
pos++;
|
||||||
ss << c;
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ss << '"';
|
}
|
||||||
return ss.str();
|
|
||||||
}
|
void BasicParser::skip(size_t n) {
|
||||||
|
n = std::min(n, source.length()-pos);
|
||||||
BasicParser::BasicParser(std::string file, std::string source) : filename(file), source(source) {
|
|
||||||
}
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
char next = source[pos++];
|
||||||
void BasicParser::skipWhitespace() {
|
if (next == '\n') {
|
||||||
while (hasNext()) {
|
line++;
|
||||||
char next = source[pos];
|
linestart = pos;
|
||||||
if (next == '\n') {
|
}
|
||||||
line++;
|
}
|
||||||
linestart = ++pos;
|
}
|
||||||
continue;
|
|
||||||
}
|
void BasicParser::skipLine() {
|
||||||
if (is_whitespace(next)) {
|
while (hasNext()) {
|
||||||
pos++;
|
if (source[pos] == '\n') {
|
||||||
} else {
|
pos++;
|
||||||
break;
|
linestart = pos;
|
||||||
}
|
line++;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
pos++;
|
||||||
void BasicParser::skip(size_t n) {
|
}
|
||||||
n = std::min(n, source.length()-pos);
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
bool BasicParser::skipTo(const std::string& substring) {
|
||||||
char next = source[pos++];
|
size_t idx = source.find(substring, pos);
|
||||||
if (next == '\n') {
|
if (idx == std::string::npos) {
|
||||||
line++;
|
skip(source.length()-pos);
|
||||||
linestart = pos;
|
return false;
|
||||||
}
|
} else {
|
||||||
}
|
skip(idx-pos);
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
void BasicParser::skipLine() {
|
}
|
||||||
while (hasNext()) {
|
|
||||||
if (source[pos] == '\n') {
|
bool BasicParser::hasNext() {
|
||||||
pos++;
|
return pos < source.length();
|
||||||
linestart = pos;
|
}
|
||||||
line++;
|
|
||||||
break;
|
bool BasicParser::isNext(const std::string& substring) {
|
||||||
}
|
if (source.length() - pos < substring.length()) {
|
||||||
pos++;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
return source.substr(pos, substring.length()) == substring;
|
||||||
|
}
|
||||||
bool BasicParser::skipTo(const std::string& substring) {
|
|
||||||
size_t idx = source.find(substring, pos);
|
char BasicParser::nextChar() {
|
||||||
if (idx == std::string::npos) {
|
if (!hasNext()) {
|
||||||
skip(source.length()-pos);
|
throw error("unexpected end");
|
||||||
return false;
|
}
|
||||||
} else {
|
return source[pos++];
|
||||||
skip(idx-pos);
|
}
|
||||||
return true;
|
|
||||||
}
|
void BasicParser::expect(char expected) {
|
||||||
}
|
char c = peek();
|
||||||
|
if (c != expected) {
|
||||||
bool BasicParser::hasNext() {
|
throw error("'"+std::string({expected})+"' expected");
|
||||||
return pos < source.length();
|
}
|
||||||
}
|
pos++;
|
||||||
|
}
|
||||||
bool BasicParser::isNext(const std::string& substring) {
|
|
||||||
if (source.length() - pos < substring.length()) {
|
void BasicParser::expect(const std::string& substring) {
|
||||||
return false;
|
if (substring.empty())
|
||||||
}
|
return;
|
||||||
return source.substr(pos, substring.length()) == substring;
|
for (uint i = 0; i < substring.length(); i++) {
|
||||||
}
|
if (source.length() <= pos + i || source[pos+i] != substring[i]) {
|
||||||
|
throw error(util::quote(substring)+" expected");
|
||||||
char BasicParser::nextChar() {
|
}
|
||||||
if (!hasNext()) {
|
}
|
||||||
throw error("unexpected end");
|
pos += substring.length();
|
||||||
}
|
}
|
||||||
return source[pos++];
|
|
||||||
}
|
void BasicParser::expectNewLine() {
|
||||||
|
while (hasNext()) {
|
||||||
void BasicParser::expect(char expected) {
|
char next = source[pos];
|
||||||
char c = peek();
|
if (next == '\n') {
|
||||||
if (c != expected) {
|
line++;
|
||||||
throw error("'"+std::string({expected})+"' expected");
|
linestart = ++pos;
|
||||||
}
|
return;
|
||||||
pos++;
|
}
|
||||||
}
|
if (is_whitespace(next)) {
|
||||||
|
pos++;
|
||||||
void BasicParser::expect(const std::string& substring) {
|
} else {
|
||||||
if (substring.empty())
|
throw error("line separator expected");
|
||||||
return;
|
}
|
||||||
for (uint i = 0; i < substring.length(); i++) {
|
}
|
||||||
if (source.length() <= pos + i || source[pos+i] != substring[i]) {
|
}
|
||||||
throw error(escape_string(substring)+" expected");
|
|
||||||
}
|
void BasicParser::goBack() {
|
||||||
}
|
if (pos) pos--;
|
||||||
pos += substring.length();
|
}
|
||||||
}
|
|
||||||
|
char BasicParser::peek() {
|
||||||
void BasicParser::expectNewLine() {
|
skipWhitespace();
|
||||||
while (hasNext()) {
|
if (pos >= source.length()) {
|
||||||
char next = source[pos];
|
throw error("unexpected end");
|
||||||
if (next == '\n') {
|
}
|
||||||
line++;
|
return source[pos];
|
||||||
linestart = ++pos;
|
}
|
||||||
return;
|
|
||||||
}
|
std::string BasicParser::readUntil(char c) {
|
||||||
if (is_whitespace(next)) {
|
int start = pos;
|
||||||
pos++;
|
while (hasNext() && source[pos] != c) {
|
||||||
} else {
|
pos++;
|
||||||
throw error("line separator expected");
|
}
|
||||||
}
|
return source.substr(start, pos-start);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
std::string BasicParser::parseName() {
|
||||||
void BasicParser::goBack() {
|
char c = peek();
|
||||||
if (pos) pos--;
|
if (!is_identifier_start(c)) {
|
||||||
}
|
if (c == '"') {
|
||||||
|
pos++;
|
||||||
char BasicParser::peek() {
|
return parseString(c);
|
||||||
skipWhitespace();
|
}
|
||||||
if (pos >= source.length()) {
|
throw error("identifier expected");
|
||||||
throw error("unexpected end");
|
}
|
||||||
}
|
int start = pos;
|
||||||
return source[pos];
|
while (hasNext() && is_identifier_part(source[pos])) {
|
||||||
}
|
pos++;
|
||||||
|
}
|
||||||
std::string BasicParser::parseName() {
|
return source.substr(start, pos-start);
|
||||||
char c = peek();
|
}
|
||||||
if (!is_identifier_start(c)) {
|
|
||||||
if (c == '"') {
|
int64_t BasicParser::parseSimpleInt(int base) {
|
||||||
pos++;
|
char c = peek();
|
||||||
return parseString(c);
|
int index = hexchar2int(c);
|
||||||
}
|
if (index == -1 || index >= base) {
|
||||||
throw error("identifier expected");
|
throw error("invalid number literal");
|
||||||
}
|
}
|
||||||
int start = pos;
|
int64_t value = index;
|
||||||
while (hasNext() && is_identifier_part(source[pos])) {
|
pos++;
|
||||||
pos++;
|
while (hasNext()) {
|
||||||
}
|
c = source[pos];
|
||||||
return source.substr(start, pos-start);
|
while (c == '_') {
|
||||||
}
|
c = source[++pos];
|
||||||
|
}
|
||||||
int64_t BasicParser::parseSimpleInt(int base) {
|
index = hexchar2int(c);
|
||||||
char c = peek();
|
if (index == -1 || index >= base) {
|
||||||
int index = hexchar2int(c);
|
return value;
|
||||||
if (index == -1 || index >= base) {
|
}
|
||||||
throw error("invalid number literal");
|
value *= base;
|
||||||
}
|
value += index;
|
||||||
int64_t value = index;
|
pos++;
|
||||||
pos++;
|
}
|
||||||
while (hasNext()) {
|
return value;
|
||||||
c = source[pos];
|
}
|
||||||
while (c == '_') {
|
|
||||||
c = source[++pos];
|
bool BasicParser::parseNumber(int sign, number_u& out) {
|
||||||
}
|
char c = peek();
|
||||||
index = hexchar2int(c);
|
int base = 10;
|
||||||
if (index == -1 || index >= base) {
|
if (c == '0' && pos + 1 < source.length() &&
|
||||||
return value;
|
(base = is_box(source[pos+1])) != 10) {
|
||||||
}
|
pos += 2;
|
||||||
value *= base;
|
out = parseSimpleInt(base);
|
||||||
value += index;
|
return true;
|
||||||
pos++;
|
} else if (c == 'i' && pos + 2 < source.length() && source[pos+1] == 'n' && source[pos+2] == 'f') {
|
||||||
}
|
pos += 3;
|
||||||
return value;
|
out = INFINITY * sign;
|
||||||
}
|
return false;
|
||||||
|
} else if (c == 'n' && pos + 2 < source.length() && source[pos+1] == 'a' && source[pos+2] == 'n') {
|
||||||
bool BasicParser::parseNumber(int sign, number_u& out) {
|
pos += 3;
|
||||||
char c = peek();
|
out = NAN * sign;
|
||||||
int base = 10;
|
return false;
|
||||||
if (c == '0' && pos + 1 < source.length() &&
|
}
|
||||||
(base = is_box(source[pos+1])) != 10) {
|
int64_t value = parseSimpleInt(base);
|
||||||
pos += 2;
|
if (!hasNext()) {
|
||||||
out.ival = parseSimpleInt(base);
|
out = value * sign;
|
||||||
return true;
|
return true;
|
||||||
} else if (c == 'i' && pos + 2 < source.length() && source[pos+1] == 'n' && source[pos+2] == 'f') {
|
}
|
||||||
pos += 3;
|
c = source[pos];
|
||||||
out.fval = INFINITY * sign;
|
if (c == 'e' || c == 'E') {
|
||||||
return false;
|
pos++;
|
||||||
} else if (c == 'n' && pos + 2 < source.length() && source[pos+1] == 'a' && source[pos+2] == 'n') {
|
int s = 1;
|
||||||
pos += 3;
|
if (peek() == '-') {
|
||||||
out.fval = NAN * sign;
|
s = -1;
|
||||||
return false;
|
pos++;
|
||||||
}
|
} else if (peek() == '+'){
|
||||||
int64_t value = parseSimpleInt(base);
|
pos++;
|
||||||
if (!hasNext()) {
|
}
|
||||||
out.ival = value * sign;
|
out = sign * value * power(10.0, s * parseSimpleInt(10));
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
c = source[pos];
|
if (c == '.') {
|
||||||
if (c == 'e' || c == 'E') {
|
pos++;
|
||||||
pos++;
|
int64_t expo = 1;
|
||||||
int s = 1;
|
while (hasNext() && source[pos] == '0') {
|
||||||
if (peek() == '-') {
|
expo *= 10;
|
||||||
s = -1;
|
pos++;
|
||||||
pos++;
|
}
|
||||||
} else if (peek() == '+'){
|
int64_t afterdot = 0;
|
||||||
pos++;
|
if (hasNext() && is_digit(source[pos])) {
|
||||||
}
|
afterdot = parseSimpleInt(10);
|
||||||
out.fval = sign * value * power(10.0, s * parseSimpleInt(10));
|
}
|
||||||
return false;
|
expo *= power(10, fmax(0, log10(afterdot) + 1));
|
||||||
}
|
c = source[pos];
|
||||||
if (c == '.') {
|
|
||||||
pos++;
|
double dvalue = (value + (afterdot / (double)expo));
|
||||||
int64_t expo = 1;
|
if (c == 'e' || c == 'E') {
|
||||||
while (hasNext() && source[pos] == '0') {
|
pos++;
|
||||||
expo *= 10;
|
int s = 1;
|
||||||
pos++;
|
if (peek() == '-') {
|
||||||
}
|
s = -1;
|
||||||
int64_t afterdot = 0;
|
pos++;
|
||||||
if (hasNext() && is_digit(source[pos])) {
|
} else if (peek() == '+'){
|
||||||
afterdot = parseSimpleInt(10);
|
pos++;
|
||||||
}
|
}
|
||||||
expo *= power(10, fmax(0, log10(afterdot) + 1));
|
out = sign * dvalue * power(10.0, s * parseSimpleInt(10));
|
||||||
c = source[pos];
|
return false;
|
||||||
|
}
|
||||||
double dvalue = (value + (afterdot / (double)expo));
|
out = sign * dvalue;
|
||||||
if (c == 'e' || c == 'E') {
|
return false;
|
||||||
pos++;
|
}
|
||||||
int s = 1;
|
out = sign * value;
|
||||||
if (peek() == '-') {
|
return true;
|
||||||
s = -1;
|
}
|
||||||
pos++;
|
|
||||||
} else if (peek() == '+'){
|
std::string BasicParser::parseString(char quote, bool closeRequired) {
|
||||||
pos++;
|
std::stringstream ss;
|
||||||
}
|
while (hasNext()) {
|
||||||
out.fval = sign * dvalue * power(10.0, s * parseSimpleInt(10));
|
char c = source[pos];
|
||||||
return false;
|
if (c == quote) {
|
||||||
}
|
pos++;
|
||||||
out.fval = sign * dvalue;
|
return ss.str();
|
||||||
return false;
|
}
|
||||||
}
|
if (c == '\\') {
|
||||||
out.ival = sign * value;
|
pos++;
|
||||||
return true;
|
c = nextChar();
|
||||||
}
|
if (c >= '0' && c <= '7') {
|
||||||
|
pos--;
|
||||||
std::string BasicParser::parseString(char quote, bool closeRequired) {
|
ss << (char)parseSimpleInt(8);
|
||||||
std::stringstream ss;
|
continue;
|
||||||
while (hasNext()) {
|
}
|
||||||
char c = source[pos];
|
switch (c) {
|
||||||
if (c == quote) {
|
case 'n': ss << '\n'; break;
|
||||||
pos++;
|
case 'r': ss << '\r'; break;
|
||||||
return ss.str();
|
case 'b': ss << '\b'; break;
|
||||||
}
|
case 't': ss << '\t'; break;
|
||||||
if (c == '\\') {
|
case 'f': ss << '\f'; break;
|
||||||
pos++;
|
case '\'': ss << '\\'; break;
|
||||||
c = nextChar();
|
case '"': ss << '"'; break;
|
||||||
if (c >= '0' && c <= '7') {
|
case '\\': ss << '\\'; break;
|
||||||
pos--;
|
case '/': ss << '/'; break;
|
||||||
ss << (char)parseSimpleInt(8);
|
case '\n': pos++; continue;
|
||||||
continue;
|
default:
|
||||||
}
|
throw error("'\\" + std::string({c}) +
|
||||||
switch (c) {
|
"' is an illegal escape");
|
||||||
case 'n': ss << '\n'; break;
|
}
|
||||||
case 'r': ss << '\r'; break;
|
continue;
|
||||||
case 'b': ss << '\b'; break;
|
}
|
||||||
case 't': ss << '\t'; break;
|
if (c == '\n' && closeRequired) {
|
||||||
case 'f': ss << '\f'; break;
|
throw error("non-closed string literal");
|
||||||
case '\'': ss << '\\'; break;
|
}
|
||||||
case '"': ss << '"'; break;
|
ss << c;
|
||||||
case '\\': ss << '\\'; break;
|
pos++;
|
||||||
case '/': ss << '/'; break;
|
}
|
||||||
case '\n': pos++; continue;
|
if (closeRequired) {
|
||||||
default:
|
throw error("unexpected end");
|
||||||
throw error("'\\" + std::string({c}) +
|
}
|
||||||
"' is an illegal escape");
|
return ss.str();
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
parsing_error BasicParser::error(std::string message) {
|
||||||
if (c == '\n' && closeRequired) {
|
return parsing_error(message, filename, source, pos, line, linestart);
|
||||||
throw error("non-closed string literal");
|
}
|
||||||
}
|
|
||||||
ss << c;
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
if (closeRequired) {
|
|
||||||
throw error("unexpected end");
|
|
||||||
}
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
parsing_error BasicParser::error(std::string message) {
|
|
||||||
return parsing_error(message, filename, source, pos, line, linestart);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
#ifndef CODERS_COMMONS_H_
|
#ifndef CODERS_COMMONS_HPP_
|
||||||
#define CODERS_COMMONS_H_
|
#define CODERS_COMMONS_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
union number_u {
|
|
||||||
double fval;
|
|
||||||
int64_t ival;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline int is_box(int c) {
|
inline int is_box(int c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -54,8 +50,6 @@ inline int hexchar2int(int c) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::string escape_string(std::string s);
|
|
||||||
|
|
||||||
class parsing_error : public std::runtime_error {
|
class parsing_error : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
std::string filename;
|
std::string filename;
|
||||||
@@ -64,20 +58,21 @@ public:
|
|||||||
uint line;
|
uint line;
|
||||||
uint linestart;
|
uint linestart;
|
||||||
|
|
||||||
parsing_error(std::string message,
|
parsing_error(
|
||||||
std::string filename,
|
std::string message,
|
||||||
std::string source,
|
std::string filename,
|
||||||
uint pos,
|
std::string source,
|
||||||
uint line,
|
uint pos,
|
||||||
uint linestart);
|
uint line,
|
||||||
|
uint linestart
|
||||||
|
);
|
||||||
std::string errorLog() const;
|
std::string errorLog() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BasicParser {
|
class BasicParser {
|
||||||
protected:
|
protected:
|
||||||
std::string filename;
|
const std::string& filename;
|
||||||
std::string source;
|
const std::string& source;
|
||||||
uint pos = 0;
|
uint pos = 0;
|
||||||
uint line = 1;
|
uint line = 1;
|
||||||
uint linestart = 0;
|
uint linestart = 0;
|
||||||
@@ -88,21 +83,24 @@ protected:
|
|||||||
bool skipTo(const std::string& substring);
|
bool skipTo(const std::string& substring);
|
||||||
void expect(char expected);
|
void expect(char expected);
|
||||||
void expect(const std::string& substring);
|
void expect(const std::string& substring);
|
||||||
char peek();
|
|
||||||
char nextChar();
|
|
||||||
bool hasNext();
|
|
||||||
bool isNext(const std::string& substring);
|
bool isNext(const std::string& substring);
|
||||||
void expectNewLine();
|
void expectNewLine();
|
||||||
void goBack();
|
void goBack();
|
||||||
|
|
||||||
std::string parseName();
|
|
||||||
int64_t parseSimpleInt(int base);
|
int64_t parseSimpleInt(int base);
|
||||||
bool parseNumber(int sign, number_u& out);
|
bool parseNumber(int sign, number_u& out);
|
||||||
std::string parseString(char chr, bool closeRequired=true);
|
std::string parseString(char chr, bool closeRequired=true);
|
||||||
|
|
||||||
parsing_error error(std::string message);
|
parsing_error error(std::string message);
|
||||||
|
|
||||||
BasicParser(std::string filename, std::string source);
|
public:
|
||||||
|
std::string readUntil(char c);
|
||||||
|
std::string parseName();
|
||||||
|
bool hasNext();
|
||||||
|
char peek();
|
||||||
|
char nextChar();
|
||||||
|
|
||||||
|
BasicParser(const std::string& file, const std::string& source);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CODERS_COMMONS_H_
|
#endif // CODERS_COMMONS_HPP_
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
#include "gzip.h"
|
#include "gzip.hpp"
|
||||||
|
|
||||||
|
#include "byte_utils.hpp"
|
||||||
|
|
||||||
#define ZLIB_CONST
|
#define ZLIB_CONST
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "byte_utils.h"
|
|
||||||
|
|
||||||
std::vector<ubyte> gzip::compress(const ubyte* src, size_t size) {
|
std::vector<ubyte> gzip::compress(const ubyte* src, size_t size) {
|
||||||
size_t buffer_size = 23+size*1.01;
|
size_t buffer_size = 23+size*1.01;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef CODERS_GZIP_H_
|
#ifndef CODERS_GZIP_HPP_
|
||||||
#define CODERS_GZIP_H_
|
#define CODERS_GZIP_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
namespace gzip {
|
namespace gzip {
|
||||||
const unsigned char MAGIC[] = "\x1F\x8B";
|
const unsigned char MAGIC[] = "\x1F\x8B";
|
||||||
@@ -18,4 +18,4 @@ namespace gzip {
|
|||||||
std::vector<ubyte> decompress(const ubyte* src, size_t size);
|
std::vector<ubyte> decompress(const ubyte* src, size_t size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CODERS_GZIP_H_
|
#endif // CODERS_GZIP_HPP_
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include "imageio.hpp"
|
||||||
|
|
||||||
|
#include "png.hpp"
|
||||||
|
#include "../graphics/core/ImageData.hpp"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
using image_reader = std::function<std::unique_ptr<ImageData>(const std::string&)>;
|
||||||
|
using image_writer = std::function<void(const std::string&, const ImageData*)>;
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, image_reader> readers {
|
||||||
|
{".png", png::load_image},
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, image_writer> writers {
|
||||||
|
{".png", png::write_image},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool imageio::is_read_supported(const std::string& extension) {
|
||||||
|
return readers.find(extension) != readers.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool imageio::is_write_supported(const std::string& extension) {
|
||||||
|
return writers.find(extension) != writers.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string extensionOf(const std::string& filename) {
|
||||||
|
return fs::u8path(filename).extension().u8string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ImageData> imageio::read(const std::string& filename) {
|
||||||
|
auto found = readers.find(extensionOf(filename));
|
||||||
|
if (found == readers.end()) {
|
||||||
|
throw std::runtime_error("file format is not supported (read): "+filename);
|
||||||
|
}
|
||||||
|
return std::unique_ptr<ImageData>(found->second(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
void imageio::write(const std::string& filename, const ImageData* image) {
|
||||||
|
auto found = writers.find(extensionOf(filename));
|
||||||
|
if (found == writers.end()) {
|
||||||
|
throw std::runtime_error("file format is not supported (write): "+filename);
|
||||||
|
}
|
||||||
|
return found->second(filename, image);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef CODERS_IMAGEIO_HPP_
|
||||||
|
#define CODERS_IMAGEIO_HPP_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class ImageData;
|
||||||
|
|
||||||
|
namespace imageio {
|
||||||
|
inline const std::string PNG = ".png";
|
||||||
|
|
||||||
|
bool is_read_supported(const std::string& extension);
|
||||||
|
bool is_write_supported(const std::string& extension);
|
||||||
|
|
||||||
|
std::unique_ptr<ImageData> read(const std::string& filename);
|
||||||
|
void write(const std::string& filename, const ImageData* image);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CODERS_IMAGEIO_HPP_
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
#include "json.h"
|
#include "json.hpp"
|
||||||
|
|
||||||
|
#include "../data/dynamic.hpp"
|
||||||
|
#include "../util/stringutil.hpp"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "commons.h"
|
|
||||||
#include "../data/dynamic.h"
|
|
||||||
|
|
||||||
using namespace json;
|
using namespace json;
|
||||||
using namespace dynamic;
|
using namespace dynamic;
|
||||||
|
|
||||||
@@ -42,10 +42,11 @@ void stringify(const Value* value,
|
|||||||
const std::string& indentstr,
|
const std::string& indentstr,
|
||||||
bool nice) {
|
bool nice) {
|
||||||
if (value->type == valtype::map) {
|
if (value->type == valtype::map) {
|
||||||
stringifyObj(value->value.map, ss, indent, indentstr, nice);
|
auto map = std::get<Map*>(value->value);
|
||||||
|
stringifyObj(map, ss, indent, indentstr, nice);
|
||||||
}
|
}
|
||||||
else if (value->type == valtype::list) {
|
else if (value->type == valtype::list) {
|
||||||
auto list = value->value.list;
|
auto list = std::get<List*>(value->value);
|
||||||
if (list->size() == 0) {
|
if (list->size() == 0) {
|
||||||
ss << "[]";
|
ss << "[]";
|
||||||
return;
|
return;
|
||||||
@@ -66,14 +67,14 @@ void stringify(const Value* value,
|
|||||||
}
|
}
|
||||||
ss << ']';
|
ss << ']';
|
||||||
} else if (value->type == valtype::boolean) {
|
} else if (value->type == valtype::boolean) {
|
||||||
ss << (value->value.boolean ? "true" : "false");
|
ss << (std::get<bool>(value->value) ? "true" : "false");
|
||||||
} else if (value->type == valtype::number) {
|
} else if (value->type == valtype::number) {
|
||||||
ss << std::setprecision(15);
|
ss << std::setprecision(15);
|
||||||
ss << value->value.decimal;
|
ss << std::get<number_t>(value->value);
|
||||||
} else if (value->type == valtype::integer) {
|
} else if (value->type == valtype::integer) {
|
||||||
ss << value->value.integer;
|
ss << std::get<integer_t>(value->value);
|
||||||
} else if (value->type == valtype::string) {
|
} else if (value->type == valtype::string) {
|
||||||
ss << escape_string(*value->value.str);
|
ss << util::escape(std::get<std::string>(value->value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ void stringifyObj(const Map* obj,
|
|||||||
newline(ss, nice, indent, indentstr);
|
newline(ss, nice, indent, indentstr);
|
||||||
}
|
}
|
||||||
Value* value = entry.second.get();
|
Value* value = entry.second.get();
|
||||||
ss << escape_string(key) << ": ";
|
ss << util::escape(key) << ": ";
|
||||||
stringify(value, ss, indent+1, indentstr, nice);
|
stringify(value, ss, indent+1, indentstr, nice);
|
||||||
index++;
|
index++;
|
||||||
if (index < obj->values.size()) {
|
if (index < obj->values.size()) {
|
||||||
@@ -116,8 +117,8 @@ std::string json::stringify(
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser(std::string filename, std::string source)
|
Parser::Parser(const std::string& filename, const std::string& source)
|
||||||
: BasicParser(filename, source) {
|
: BasicParser(filename, source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map* Parser::parse() {
|
Map* Parser::parse() {
|
||||||
@@ -189,10 +190,10 @@ Value* Parser::parseValue() {
|
|||||||
number_u num;
|
number_u num;
|
||||||
valtype type;
|
valtype type;
|
||||||
if (parseNumber(next == '-' ? -1 : 1, num)) {
|
if (parseNumber(next == '-' ? -1 : 1, num)) {
|
||||||
val.integer = num.ival;
|
val = std::get<integer_t>(num);
|
||||||
type = valtype::integer;
|
type = valtype::integer;
|
||||||
} else {
|
} else {
|
||||||
val.decimal = num.fval;
|
val = std::get<number_t>(num);
|
||||||
type = valtype::number;
|
type = valtype::number;
|
||||||
}
|
}
|
||||||
return new Value(type, val);
|
return new Value(type, val);
|
||||||
@@ -200,53 +201,53 @@ Value* Parser::parseValue() {
|
|||||||
if (is_identifier_start(next)) {
|
if (is_identifier_start(next)) {
|
||||||
std::string literal = parseName();
|
std::string literal = parseName();
|
||||||
if (literal == "true") {
|
if (literal == "true") {
|
||||||
val.boolean = true;
|
val = true;
|
||||||
return new Value(valtype::boolean, val);
|
return new Value(valtype::boolean, val);
|
||||||
} else if (literal == "false") {
|
} else if (literal == "false") {
|
||||||
val.boolean = false;
|
val = false;
|
||||||
return new Value(valtype::boolean, val);
|
return new Value(valtype::boolean, val);
|
||||||
} else if (literal == "inf") {
|
} else if (literal == "inf") {
|
||||||
val.decimal = INFINITY;
|
val = INFINITY;
|
||||||
return new Value(valtype::number, val);
|
return new Value(valtype::number, val);
|
||||||
} else if (literal == "nan") {
|
} else if (literal == "nan") {
|
||||||
val.decimal = NAN;
|
val = NAN;
|
||||||
return new Value(valtype::number, val);
|
return new Value(valtype::number, val);
|
||||||
}
|
}
|
||||||
throw error("invalid literal ");
|
throw error("invalid literal ");
|
||||||
}
|
}
|
||||||
if (next == '{') {
|
if (next == '{') {
|
||||||
val.map = parseObject();
|
val = parseObject();
|
||||||
return new Value(valtype::map, val);
|
return new Value(valtype::map, val);
|
||||||
}
|
}
|
||||||
if (next == '[') {
|
if (next == '[') {
|
||||||
val.list = parseList();
|
val = parseList();
|
||||||
return new Value(valtype::list, val);
|
return new Value(valtype::list, val);
|
||||||
}
|
}
|
||||||
if (is_digit(next)) {
|
if (is_digit(next)) {
|
||||||
number_u num;
|
number_u num;
|
||||||
valtype type;
|
valtype type;
|
||||||
if (parseNumber(1, num)) {
|
if (parseNumber(1, num)) {
|
||||||
val.integer = num.ival;
|
val = std::get<integer_t>(num);
|
||||||
type = valtype::integer;
|
type = valtype::integer;
|
||||||
} else {
|
} else {
|
||||||
val.decimal = num.fval;
|
val = std::get<number_t>(num);
|
||||||
type = valtype::number;
|
type = valtype::number;
|
||||||
}
|
}
|
||||||
return new Value(type, val);
|
return new Value(type, val);
|
||||||
}
|
}
|
||||||
if (next == '"' || next == '\'') {
|
if (next == '"' || next == '\'') {
|
||||||
pos++;
|
pos++;
|
||||||
val.str = new std::string(parseString(next));
|
val = parseString(next);
|
||||||
return new Value(valtype::string, val);
|
return new Value(valtype::string, val);
|
||||||
}
|
}
|
||||||
throw error("unexpected character '"+std::string({next})+"'");
|
throw error("unexpected character '"+std::string({next})+"'");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Map> json::parse(std::string filename, std::string source) {
|
std::unique_ptr<Map> json::parse(const std::string& filename, const std::string& source) {
|
||||||
Parser parser(filename, source);
|
Parser parser(filename, source);
|
||||||
return std::unique_ptr<Map>(parser.parse());
|
return std::unique_ptr<Map>(parser.parse());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Map> json::parse(std::string source) {
|
std::unique_ptr<Map> json::parse(const std::string& source) {
|
||||||
return parse("<string>", source);
|
return parse("<string>", source);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
#ifndef CODERS_JSON_H_
|
#ifndef CODERS_JSON_HPP_
|
||||||
#define CODERS_JSON_H_
|
#define CODERS_JSON_HPP_
|
||||||
|
|
||||||
|
#include "commons.hpp"
|
||||||
|
#include "binary_json.hpp"
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -7,11 +12,6 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "commons.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include "binary_json.h"
|
|
||||||
|
|
||||||
namespace dynamic {
|
namespace dynamic {
|
||||||
class Map;
|
class Map;
|
||||||
class List;
|
class List;
|
||||||
@@ -24,13 +24,13 @@ namespace json {
|
|||||||
dynamic::Map* parseObject();
|
dynamic::Map* parseObject();
|
||||||
dynamic::Value* parseValue();
|
dynamic::Value* parseValue();
|
||||||
public:
|
public:
|
||||||
Parser(std::string filename, std::string source);
|
Parser(const std::string& filename, const std::string& source);
|
||||||
|
|
||||||
dynamic::Map* parse();
|
dynamic::Map* parse();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<dynamic::Map> parse(std::string filename, std::string source);
|
extern std::unique_ptr<dynamic::Map> parse(const std::string& filename, const std::string& source);
|
||||||
extern std::unique_ptr<dynamic::Map> parse(std::string source);
|
extern std::unique_ptr<dynamic::Map> parse(const std::string& source);
|
||||||
|
|
||||||
extern std::string stringify(
|
extern std::string stringify(
|
||||||
const dynamic::Map* obj,
|
const dynamic::Map* obj,
|
||||||
@@ -38,4 +38,4 @@ namespace json {
|
|||||||
const std::string& indent);
|
const std::string& indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CODERS_JSON_H_
|
#endif // CODERS_JSON_HPP_
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
#include "ogg.h"
|
#include "ogg.hpp"
|
||||||
|
|
||||||
|
#include "../debug/Logger.hpp"
|
||||||
|
#include "../audio/audio.hpp"
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
|
||||||
#include <vorbis/codec.h>
|
#include <vorbis/codec.h>
|
||||||
#include <vorbis/vorbisfile.h>
|
#include <vorbis/vorbisfile.h>
|
||||||
|
|
||||||
#include "../audio/audio.h"
|
static debug::Logger logger("ogg");
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
using namespace audio;
|
using namespace audio;
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ audio::PCM* ogg::load_pcm(const std::filesystem::path& file, bool headerOnly) {
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
eof = true;
|
eof = true;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
std::cerr << "ogg::load_pcm: " << vorbis_error_message(ret) << std::endl;
|
logger.error() << "ogg::load_pcm: " << vorbis_error_message(ret);
|
||||||
} else {
|
} else {
|
||||||
data.insert(data.end(), std::begin(buffer), std::begin(buffer)+ret);
|
data.insert(data.end(), std::begin(buffer), std::begin(buffer)+ret);
|
||||||
}
|
}
|
||||||
@@ -98,7 +100,7 @@ public:
|
|||||||
int bitstream = 0;
|
int bitstream = 0;
|
||||||
long bytes = ov_read(&vf, buffer, bufferSize, 0, 2, true, &bitstream);
|
long bytes = ov_read(&vf, buffer, bufferSize, 0, 2, true, &bitstream);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
std::cerr << "ogg::load_pcm: " << vorbis_error_message(bytes) << " " << bytes << std::endl;
|
logger.error() << "ogg::load_pcm: " << vorbis_error_message(bytes) << " " << bytes;
|
||||||
return PCMStream::ERROR;
|
return PCMStream::ERROR;
|
||||||
}
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef CODERS_OGG_H_
|
#ifndef CODERS_OGG_HPP_
|
||||||
#define CODERS_OGG_H_
|
#define CODERS_OGG_HPP_
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
@@ -13,4 +13,4 @@ namespace ogg {
|
|||||||
extern audio::PCMStream* create_stream(const std::filesystem::path& file);
|
extern audio::PCMStream* create_stream(const std::filesystem::path& file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CODERS_OGG_H_
|
#endif // CODERS_OGG_HPP_
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
#include "png.h"
|
#include "png.hpp"
|
||||||
|
|
||||||
|
#include "../graphics/core/ImageData.hpp"
|
||||||
|
#include "../graphics/core/Texture.hpp"
|
||||||
|
#include "../files/files.hpp"
|
||||||
|
#include "../debug/Logger.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include "../graphics/ImageData.h"
|
static debug::Logger logger("png-coder");
|
||||||
#include "../graphics/Texture.h"
|
|
||||||
#include "../files/files.h"
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#define LIBPNG
|
#define LIBPNG
|
||||||
@@ -19,78 +21,76 @@
|
|||||||
int _png_write(const char* filename, uint width, uint height, const ubyte* data, bool alpha) {
|
int _png_write(const char* filename, uint width, uint height, const ubyte* data, bool alpha) {
|
||||||
uint pixsize = alpha ? 4 : 3;
|
uint pixsize = alpha ? 4 : 3;
|
||||||
|
|
||||||
// Open file for writing (binary mode)
|
// Open file for writing (binary mode)
|
||||||
FILE* fp = fopen(filename, "wb");
|
FILE* fp = fopen(filename, "wb");
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
fprintf(stderr, "Could not open file %s for writing\n", filename);
|
logger.error() << "could not open file " << filename << " for writing";
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize write structure
|
// Initialize write structure
|
||||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
if (png_ptr == nullptr) {
|
if (png_ptr == nullptr) {
|
||||||
fprintf(stderr, "Could not allocate write struct\n");
|
logger.error() << "could not allocate write struct";
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp)nullptr);
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize info structure
|
// Initialize info structure
|
||||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
if (info_ptr == nullptr) {
|
if (info_ptr == nullptr) {
|
||||||
fprintf(stderr, "Could not allocate info struct\n");
|
logger.error() << "could not allocate info struct";
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp)nullptr);
|
png_destroy_write_struct(&png_ptr, (png_infopp)nullptr);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup Exception handling
|
// Setup Exception handling
|
||||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
fprintf(stderr, "Error during png creation\n");
|
logger.error() << "error during png creation";
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp)nullptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
png_init_io(png_ptr, fp);
|
png_init_io(png_ptr, fp);
|
||||||
|
|
||||||
// Write header (8 bit colour depth)
|
// Write header (8 bit colour depth)
|
||||||
png_set_IHDR(png_ptr, info_ptr, width, height,
|
png_set_IHDR(png_ptr, info_ptr, width, height,
|
||||||
8,
|
8,
|
||||||
alpha ? PNG_COLOR_TYPE_RGBA :
|
alpha ? PNG_COLOR_TYPE_RGBA :
|
||||||
PNG_COLOR_TYPE_RGB,
|
PNG_COLOR_TYPE_RGB,
|
||||||
PNG_INTERLACE_NONE,
|
PNG_INTERLACE_NONE,
|
||||||
PNG_COMPRESSION_TYPE_BASE,
|
PNG_COMPRESSION_TYPE_BASE,
|
||||||
PNG_FILTER_TYPE_BASE);
|
PNG_FILTER_TYPE_BASE);
|
||||||
|
|
||||||
png_write_info(png_ptr, info_ptr);
|
png_write_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
std::unique_ptr<png_byte[]> row(new png_byte[pixsize * width]);
|
auto row = std::make_unique<png_byte[]>(pixsize * width);
|
||||||
|
// Write image data
|
||||||
// Write image data
|
for (uint y = 0; y < height; y++) {
|
||||||
for (uint y = 0; y < height; y++) {
|
for (uint x = 0; x < width; x++) {
|
||||||
for (uint x = 0; x < width; x++) {
|
|
||||||
for (uint i = 0; i < pixsize; i++) {
|
for (uint i = 0; i < pixsize; i++) {
|
||||||
row[x * pixsize + i] = (png_byte)data[(y * width + x) * pixsize + i];
|
row[x * pixsize + i] = (png_byte)data[(y * width + x) * pixsize + i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
png_write_row(png_ptr, row.get());
|
png_write_row(png_ptr, row.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// End write
|
// End write
|
||||||
png_write_end(png_ptr, nullptr);
|
png_write_end(png_ptr, nullptr);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp)nullptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageData* _png_load(const char* file){
|
std::unique_ptr<ImageData> _png_load(const char* file){
|
||||||
FILE* fp = nullptr;
|
FILE* fp = nullptr;
|
||||||
if ((fp = fopen(file, "rb")) == nullptr) {
|
if ((fp = fopen(file, "rb")) == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -175,12 +175,12 @@ ImageData* _png_load(const char* file){
|
|||||||
format = ImageFormat::rgb888;
|
format = ImageFormat::rgb888;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Color type %d not supported!\n", color_type);
|
logger.error() << "color type " << color_type << " is not supported!";
|
||||||
png_destroy_read_struct(&png, &info, &end_info);
|
png_destroy_read_struct(&png, &info, &end_info);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ImageData* image = new ImageData(format, width, height, (void*)image_data.release());
|
auto image = std::make_unique<ImageData>(format, width, height, (void*)image_data.release());
|
||||||
png_destroy_read_struct(&png, &info, &end_info);
|
png_destroy_read_struct(&png, &info, &end_info);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return image;
|
return image;
|
||||||
@@ -194,172 +194,159 @@ ImageData* _png_load(const char* file){
|
|||||||
static const int SPNG_SUCCESS = 0;
|
static const int SPNG_SUCCESS = 0;
|
||||||
//returns spng result code
|
//returns spng result code
|
||||||
int _png_write(const char* filename, uint width, uint height, const ubyte* data, bool alpha) {
|
int _png_write(const char* filename, uint width, uint height, const ubyte* data, bool alpha) {
|
||||||
int fmt;
|
int fmt;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
spng_ctx* ctx = nullptr;
|
spng_ctx* ctx = nullptr;
|
||||||
spng_ihdr ihdr = { 0 };
|
spng_ihdr ihdr = { 0 };
|
||||||
uint pixsize = alpha ? 4 : 3;
|
uint pixsize = alpha ? 4 : 3;
|
||||||
|
|
||||||
ctx = spng_ctx_new(SPNG_CTX_ENCODER);
|
ctx = spng_ctx_new(SPNG_CTX_ENCODER);
|
||||||
spng_set_option(ctx, SPNG_ENCODE_TO_BUFFER, 1);
|
spng_set_option(ctx, SPNG_ENCODE_TO_BUFFER, 1);
|
||||||
|
|
||||||
ihdr.width = width;
|
ihdr.width = width;
|
||||||
ihdr.height = height;
|
ihdr.height = height;
|
||||||
ihdr.color_type = alpha ? SPNG_COLOR_TYPE_TRUECOLOR_ALPHA : SPNG_COLOR_TYPE_TRUECOLOR;
|
ihdr.color_type = alpha ? SPNG_COLOR_TYPE_TRUECOLOR_ALPHA : SPNG_COLOR_TYPE_TRUECOLOR;
|
||||||
ihdr.bit_depth = 8;
|
ihdr.bit_depth = 8;
|
||||||
|
|
||||||
spng_set_ihdr(ctx, &ihdr);
|
spng_set_ihdr(ctx, &ihdr);
|
||||||
fmt = SPNG_FMT_PNG;
|
fmt = SPNG_FMT_PNG;
|
||||||
ret = spng_encode_image(ctx, data, (size_t)width * (size_t)height * pixsize , fmt, SPNG_ENCODE_FINALIZE);
|
ret = spng_encode_image(ctx, data, (size_t)width * (size_t)height * pixsize , fmt, SPNG_ENCODE_FINALIZE);
|
||||||
if (ret != SPNG_SUCCESS) {
|
if (ret != SPNG_SUCCESS) {
|
||||||
printf("spng_encode_image() error: %s\n", spng_strerror(ret));
|
logger.error() << "spng_encode_image() error: " << spng_strerror(ret);
|
||||||
fflush(stdout);
|
spng_ctx_free(ctx);
|
||||||
spng_ctx_free(ctx);
|
return ret;
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
size_t png_size;
|
size_t png_size;
|
||||||
void* png_buf = spng_get_png_buffer(ctx, &png_size, &ret);
|
void* png_buf = spng_get_png_buffer(ctx, &png_size, &ret);
|
||||||
|
|
||||||
if (png_buf == nullptr) {
|
if (png_buf == nullptr) {
|
||||||
printf("spng_get_png_buffer() error: %s\n", spng_strerror(ret));
|
logger.error() << "spng_get_png_buffer() error: " << spng_strerror(ret);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
files::write_bytes(filename, (const unsigned char*)png_buf, png_size);
|
files::write_bytes(filename, (const unsigned char*)png_buf, png_size);
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
spng_ctx_free(ctx);
|
||||||
spng_ctx_free(ctx);
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageData* _png_load(const char* file){
|
std::unique_ptr<ImageData> _png_load(const char* file){
|
||||||
int r = 0;
|
int r = 0;
|
||||||
FILE *png = nullptr;
|
FILE *png = nullptr;
|
||||||
char *pngbuf = nullptr;
|
char *pngbuf = nullptr;
|
||||||
spng_ctx *ctx = nullptr;
|
spng_ctx *ctx = nullptr;
|
||||||
unsigned char *out = nullptr;
|
unsigned char *out = nullptr;
|
||||||
|
|
||||||
png = fopen(file, "rb");
|
png = fopen(file, "rb");
|
||||||
if (png == nullptr){
|
if (png == nullptr){
|
||||||
std::cerr << "could not to open file " << file << std::endl;
|
logger.error() << "could not to open file " << file;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(png, 0, SEEK_END);
|
fseek(png, 0, SEEK_END);
|
||||||
long siz_pngbuf = ftell(png);
|
long siz_pngbuf = ftell(png);
|
||||||
rewind(png);
|
rewind(png);
|
||||||
if(siz_pngbuf < 1) {
|
if(siz_pngbuf < 1) {
|
||||||
fclose(png);
|
fclose(png);
|
||||||
std::cerr << "could not to read file " << file << std::endl;
|
logger.error() << "could not to read file " << file;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
pngbuf = new char[siz_pngbuf];
|
pngbuf = new char[siz_pngbuf];
|
||||||
if(fread(pngbuf, siz_pngbuf, 1, png) != 1){ //check of read elements count
|
if(fread(pngbuf, siz_pngbuf, 1, png) != 1){ //check of read elements count
|
||||||
fclose(png);
|
fclose(png);
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
std::cerr << "fread() failed" << std::endl;
|
logger.error() << "fread() failed: " << file;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
fclose(png); // <- finally closing file
|
fclose(png); // <- finally closing file
|
||||||
ctx = spng_ctx_new(0);
|
ctx = spng_ctx_new(0);
|
||||||
if (ctx == nullptr){
|
if (ctx == nullptr){
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
std::cerr << "spng_ctx_new() failed" << std::endl;
|
logger.error() << "spng_ctx_new() failed";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
r = spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE);
|
r = spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE);
|
||||||
if (r != SPNG_SUCCESS){
|
if (r != SPNG_SUCCESS){
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
spng_ctx_free(ctx);
|
spng_ctx_free(ctx);
|
||||||
std::cerr << "spng_set_crc_action() error: " << spng_strerror(r) << std::endl;
|
logger.error() << "spng_set_crc_action(): " << spng_strerror(r);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
r = spng_set_png_buffer(ctx, pngbuf, siz_pngbuf);
|
r = spng_set_png_buffer(ctx, pngbuf, siz_pngbuf);
|
||||||
if (r != SPNG_SUCCESS){
|
if (r != SPNG_SUCCESS){
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
spng_ctx_free(ctx);
|
spng_ctx_free(ctx);
|
||||||
std::cerr << "spng_set_png_buffer() error: " << spng_strerror(r) << std::endl;
|
logger.error() << "spng_set_png_buffer(): " << spng_strerror(r);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
spng_ihdr ihdr;
|
spng_ihdr ihdr;
|
||||||
r = spng_get_ihdr(ctx, &ihdr);
|
r = spng_get_ihdr(ctx, &ihdr);
|
||||||
if (r != SPNG_SUCCESS){
|
if (r != SPNG_SUCCESS){
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
spng_ctx_free(ctx);
|
spng_ctx_free(ctx);
|
||||||
std::cerr << "spng_get_ihdr() error: " << spng_strerror(r) << std::endl;
|
logger.error() << "spng_get_ihdr(): " << spng_strerror(r);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
//// Unused "something"
|
|
||||||
//const char *clr_type_str;
|
|
||||||
//if(ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE)
|
|
||||||
// clr_type_str = "grayscale";
|
|
||||||
//else if(ihdr.color_type == SPNG_COLOR_TYPE_TRUECOLOR)
|
|
||||||
// clr_type_str = "truecolor";
|
|
||||||
//else if(ihdr.color_type == SPNG_COLOR_TYPE_INDEXED)
|
|
||||||
// clr_type_str = "indexed color";
|
|
||||||
//else if(ihdr.color_type == SPNG_COLOR_TYPE_GRAYSCALE_ALPHA)
|
|
||||||
// clr_type_str = "grayscale with alpha";
|
|
||||||
//else
|
|
||||||
// clr_type_str = "truecolor with alpha";
|
|
||||||
|
|
||||||
size_t out_size;
|
size_t out_size;
|
||||||
r = spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size);
|
r = spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size);
|
||||||
if (r != SPNG_SUCCESS){
|
if (r != SPNG_SUCCESS){
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
spng_ctx_free(ctx);
|
spng_ctx_free(ctx);
|
||||||
std::cerr << "spng_decoded_image_size() error: " << spng_strerror(r) << std::endl;
|
logger.error() << "spng_decoded_image_size(): " << spng_strerror(r);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
out = new unsigned char[out_size];
|
out = new unsigned char[out_size];
|
||||||
r = spng_decode_image(ctx, out, out_size, SPNG_FMT_RGBA8, 0);
|
r = spng_decode_image(ctx, out, out_size, SPNG_FMT_RGBA8, 0);
|
||||||
if (r != SPNG_SUCCESS){
|
if (r != SPNG_SUCCESS){
|
||||||
delete[] out;
|
delete[] out;
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
spng_ctx_free(ctx);
|
spng_ctx_free(ctx);
|
||||||
std::cerr << "spng_decode_image() error: " << spng_strerror(r) << std::endl;
|
logger.error() << "spng_decode_image(): " << spng_strerror(r);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* flipped = new unsigned char[out_size];
|
unsigned char* flipped = new unsigned char[out_size];
|
||||||
|
|
||||||
for (size_t i = 0; i < ihdr.height; i+=1){
|
for (size_t i = 0; i < ihdr.height; i+=1){
|
||||||
size_t rowsize = ihdr.width*4;
|
size_t rowsize = ihdr.width*4;
|
||||||
for (size_t j = 0; j < rowsize; j++){
|
for (size_t j = 0; j < rowsize; j++){
|
||||||
flipped[(ihdr.height-i-1)*rowsize+j] = out[i*rowsize+j];
|
flipped[(ihdr.height-i-1)*rowsize+j] = out[i*rowsize+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] out; // <- finally delete out // no, delete spng usage
|
delete[] out; // <- finally delete out // no, delete spng usage
|
||||||
|
|
||||||
ImageData* image = new ImageData(ImageFormat::rgba8888, ihdr.width, ihdr.height, (void*)flipped);
|
auto image = std::make_unique<ImageData>(ImageFormat::rgba8888, ihdr.width, ihdr.height, (void*)flipped);
|
||||||
|
|
||||||
delete[] pngbuf;
|
delete[] pngbuf;
|
||||||
spng_ctx_free(ctx);
|
spng_ctx_free(ctx);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ImageData* png::load_image(std::string filename) {
|
std::unique_ptr<ImageData> png::load_image(const std::string& filename) {
|
||||||
ImageData* image (_png_load(filename.c_str()));
|
auto image = _png_load(filename.c_str());
|
||||||
if (image == nullptr) {
|
if (image == nullptr) {
|
||||||
std::cerr << "Could not load image " << filename << std::endl;
|
throw std::runtime_error("could not load image "+filename);
|
||||||
return nullptr;
|
}
|
||||||
}
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture* png::load_texture(std::string filename) {
|
std::unique_ptr<Texture> png::load_texture(const std::string& filename) {
|
||||||
std::unique_ptr<ImageData> image (_png_load(filename.c_str()));
|
auto image = load_image(filename);
|
||||||
if (image == nullptr){
|
auto texture = Texture::from(image.get());
|
||||||
std::cerr << "Could not load texture " << filename << std::endl;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto texture = Texture::from(image.get());
|
|
||||||
texture->setNearestFilter();
|
texture->setNearestFilter();
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void png::write_image(std::string filename, const ImageData* image) {
|
void png::write_image(const std::string& filename, const ImageData* image) {
|
||||||
_png_write(filename.c_str(), image->getWidth(), image->getHeight(), (const ubyte*)image->getData(), image->getFormat() == ImageFormat::rgba8888);
|
_png_write(
|
||||||
}
|
filename.c_str(),
|
||||||
|
image->getWidth(),
|
||||||
|
image->getHeight(),
|
||||||
|
(const ubyte*)image->getData(),
|
||||||
|
image->getFormat() == ImageFormat::rgba8888
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
#ifndef CODERS_PNG_H_
|
|
||||||
#define CODERS_PNG_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
class Texture;
|
|
||||||
class ImageData;
|
|
||||||
|
|
||||||
namespace png {
|
|
||||||
extern ImageData* load_image(std::string filename);
|
|
||||||
extern void write_image(std::string filename, const ImageData* image);
|
|
||||||
extern Texture* load_texture(std::string filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CODERS_PNG_H_ */
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef CODERS_PNG_HPP_
|
||||||
|
#define CODERS_PNG_HPP_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Texture;
|
||||||
|
class ImageData;
|
||||||
|
|
||||||
|
namespace png {
|
||||||
|
std::unique_ptr<ImageData> load_image(const std::string& filename);
|
||||||
|
void write_image(const std::string& filename, const ImageData* image);
|
||||||
|
std::unique_ptr<Texture> load_texture(const std::string& filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CODERS_PNG_HPP_
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
#include "rle.hpp"
|
||||||
|
|
||||||
|
size_t rle::decode(const ubyte* src, size_t srclen, ubyte* dst) {
|
||||||
|
size_t offset = 0;
|
||||||
|
for (size_t i = 0; i < srclen;) {
|
||||||
|
ubyte len = src[i++];
|
||||||
|
ubyte c = src[i++];
|
||||||
|
for (size_t j = 0; j <= len; j++) {
|
||||||
|
dst[offset++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rle::encode(const ubyte* src, size_t srclen, ubyte* dst) {
|
||||||
|
if (srclen == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t offset = 0;
|
||||||
|
ubyte counter = 0;
|
||||||
|
ubyte c = src[0];
|
||||||
|
for (size_t i = 1; i < srclen; i++) {
|
||||||
|
ubyte cnext = src[i];
|
||||||
|
if (cnext != c || counter == 255) {
|
||||||
|
dst[offset++] = counter;
|
||||||
|
dst[offset++] = c;
|
||||||
|
c = cnext;
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst[offset++] = counter;
|
||||||
|
dst[offset++] = c;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t extrle::decode(const ubyte* src, size_t srclen, ubyte* dst) {
|
||||||
|
size_t offset = 0;
|
||||||
|
for (size_t i = 0; i < srclen;) {
|
||||||
|
uint len = src[i++];
|
||||||
|
if (len & 0x80) {
|
||||||
|
len &= 0x7F;
|
||||||
|
len |= ((uint)src[i++]) << 7;
|
||||||
|
}
|
||||||
|
ubyte c = src[i++];
|
||||||
|
for (size_t j = 0; j <= len; j++) {
|
||||||
|
dst[offset++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t extrle::encode(const ubyte* src, size_t srclen, ubyte* dst) {
|
||||||
|
if (srclen == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t offset = 0;
|
||||||
|
uint counter = 0;
|
||||||
|
ubyte c = src[0];
|
||||||
|
for (size_t i = 1; i < srclen; i++) {
|
||||||
|
ubyte cnext = src[i];
|
||||||
|
if (cnext != c || counter == max_sequence) {
|
||||||
|
if (counter >= 0x80) {
|
||||||
|
dst[offset++] = 0x80 | (counter & 0x7F);
|
||||||
|
dst[offset++] = counter >> 7;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dst[offset++] = counter;
|
||||||
|
}
|
||||||
|
dst[offset++] = c;
|
||||||
|
c = cnext;
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (counter >= 0x80) {
|
||||||
|
dst[offset++] = 0x80 | (counter & 0x7F);
|
||||||
|
dst[offset++] = counter >> 7;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dst[offset++] = counter;
|
||||||
|
}
|
||||||
|
dst[offset++] = c;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef CODERS_RLE_HPP_
|
||||||
|
#define CODERS_RLE_HPP_
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
|
||||||
|
namespace rle {
|
||||||
|
size_t encode(const ubyte* src, size_t length, ubyte* dst);
|
||||||
|
size_t decode(const ubyte* src, size_t length, ubyte* dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace extrle {
|
||||||
|
constexpr uint max_sequence = 0x7FFF;
|
||||||
|
size_t encode(const ubyte* src, size_t length, ubyte* dst);
|
||||||
|
size_t decode(const ubyte* src, size_t length, ubyte* dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CODERS_RLE_HPP_
|
||||||
@@ -1,249 +1,135 @@
|
|||||||
#include "toml.h"
|
#include "toml.hpp"
|
||||||
#include "commons.h"
|
|
||||||
|
#include "commons.hpp"
|
||||||
#include <math.h>
|
#include "../data/setting.hpp"
|
||||||
#include <iostream>
|
#include "../data/dynamic.hpp"
|
||||||
#include <iomanip>
|
#include "../util/stringutil.hpp"
|
||||||
#include <sstream>
|
#include "../files/settings_io.hpp"
|
||||||
#include <assert.h>
|
|
||||||
|
#include <math.h>
|
||||||
using std::string;
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
using namespace toml;
|
#include <sstream>
|
||||||
|
#include <assert.h>
|
||||||
Section::Section(string name) : name(name) {
|
|
||||||
}
|
using namespace toml;
|
||||||
|
|
||||||
void Section::add(std::string name, Field field) {
|
class Reader : public BasicParser {
|
||||||
if (fields.find(name) != fields.end()) {
|
SettingsHandler& handler;
|
||||||
throw std::runtime_error("field duplication");
|
|
||||||
}
|
void skipWhitespace() override {
|
||||||
fields[name] = field;
|
BasicParser::skipWhitespace();
|
||||||
keyOrder.push_back(name);
|
if (hasNext() && source[pos] == '#') {
|
||||||
}
|
skipLine();
|
||||||
|
if (hasNext() && is_whitespace(peek())) {
|
||||||
void Section::add(string name, bool* ptr) {
|
skipWhitespace();
|
||||||
add(name, {fieldtype::ftbool, ptr});
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void Section::add(string name, int* ptr) {
|
void readSection(const std::string& section) {
|
||||||
add(name, {fieldtype::ftint, ptr});
|
while (hasNext()) {
|
||||||
}
|
skipWhitespace();
|
||||||
|
if (!hasNext()) {
|
||||||
void Section::add(string name, uint* ptr) {
|
break;
|
||||||
add(name, {fieldtype::ftuint, ptr});
|
}
|
||||||
}
|
char c = nextChar();
|
||||||
|
if (c == '[') {
|
||||||
void Section::add(string name, float* ptr) {
|
std::string name = parseName();
|
||||||
add(name, {fieldtype::ftfloat, ptr});
|
pos++;
|
||||||
}
|
readSection(name);
|
||||||
|
return;
|
||||||
void Section::add(string name, string* ptr) {
|
}
|
||||||
add(name, {fieldtype::ftstring, ptr});
|
pos--;
|
||||||
}
|
std::string name = section+"."+parseName();
|
||||||
|
expect('=');
|
||||||
string Section::getName() const {
|
c = peek();
|
||||||
return name;
|
if (is_digit(c)) {
|
||||||
}
|
number_u num;
|
||||||
|
parseNumber(1, num);
|
||||||
const Field* Section::field(std::string name) const {
|
if (handler.has(name)) {
|
||||||
auto found = fields.find(name);
|
handler.setValue(name, *dynamic::Value::of(num));
|
||||||
if (found == fields.end()) {
|
}
|
||||||
return nullptr;
|
} else if (c == '-' || c == '+') {
|
||||||
}
|
int sign = c == '-' ? -1 : 1;
|
||||||
return &found->second;
|
pos++;
|
||||||
}
|
number_u num;
|
||||||
|
parseNumber(sign, num);
|
||||||
const std::vector<std::string>& Section::keys() const {
|
if (handler.has(name)) {
|
||||||
return keyOrder;
|
handler.setValue(name, *dynamic::Value::of(num));
|
||||||
}
|
}
|
||||||
|
} else if (is_identifier_start(c)) {
|
||||||
Wrapper::~Wrapper() {
|
std::string identifier = parseName();
|
||||||
for (auto entry : sections) {
|
if (handler.has(name)) {
|
||||||
delete entry.second;
|
if (identifier == "true" || identifier == "false") {
|
||||||
}
|
bool flag = identifier == "true";
|
||||||
}
|
handler.setValue(name, *dynamic::Value::boolean(flag));
|
||||||
|
} else if (identifier == "inf") {
|
||||||
Section& Wrapper::add(std::string name) {
|
handler.setValue(name, *dynamic::Value::of(INFINITY));
|
||||||
if (sections.find(name) != sections.end()) {
|
} else if (identifier == "nan") {
|
||||||
throw std::runtime_error("section duplication");
|
handler.setValue(name, *dynamic::Value::of(NAN));
|
||||||
}
|
}
|
||||||
Section* section = new Section(name);
|
}
|
||||||
sections[name] = section;
|
} else if (c == '"' || c == '\'') {
|
||||||
keyOrder.push_back(name);
|
pos++;
|
||||||
return *section;
|
std::string str = parseString(c);
|
||||||
}
|
if (handler.has(name)) {
|
||||||
|
handler.setValue(name, *dynamic::Value::of(str));
|
||||||
Section* Wrapper::section(std::string name) {
|
}
|
||||||
auto found = sections.find(name);
|
} else {
|
||||||
if (found == sections.end()) {
|
throw error("feature is not supported");
|
||||||
return nullptr;
|
}
|
||||||
}
|
expectNewLine();
|
||||||
return found->second;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Wrapper::write() const {
|
public:
|
||||||
std::stringstream ss;
|
Reader(
|
||||||
for (string key : keyOrder) {
|
SettingsHandler& handler,
|
||||||
const Section* section = sections.at(key);
|
const std::string& file,
|
||||||
ss << "[" << key << "]\n";
|
const std::string& source)
|
||||||
for (const string& key : section->keys()) {
|
: BasicParser(file, source), handler(handler) {
|
||||||
ss << key << " = ";
|
}
|
||||||
const Field* field = section->field(key);
|
|
||||||
assert(field != nullptr);
|
void read() {
|
||||||
switch (field->type) {
|
skipWhitespace();
|
||||||
case fieldtype::ftbool:
|
if (!hasNext()) {
|
||||||
ss << (*((bool*)field->ptr) ? "true" : "false");
|
return;
|
||||||
break;
|
}
|
||||||
case fieldtype::ftint: ss << *((int*)field->ptr); break;
|
readSection("");
|
||||||
case fieldtype::ftuint: ss << *((uint*)field->ptr); break;
|
}
|
||||||
case fieldtype::ftfloat: ss << *((float*)field->ptr); break;
|
};
|
||||||
case fieldtype::ftstring:
|
|
||||||
ss << escape_string(*((const string*)field->ptr));
|
void toml::parse(
|
||||||
break;
|
SettingsHandler& handler,
|
||||||
}
|
const std::string& file,
|
||||||
ss << "\n";
|
const std::string& source
|
||||||
}
|
) {
|
||||||
ss << "\n";
|
Reader reader(handler, file, source);
|
||||||
}
|
reader.read();
|
||||||
return ss.str();
|
}
|
||||||
}
|
|
||||||
|
std::string toml::stringify(SettingsHandler& handler) {
|
||||||
Reader::Reader(Wrapper* wrapper, string file, string source) : BasicParser(file, source), wrapper(wrapper) {
|
auto& sections = handler.getSections();
|
||||||
}
|
|
||||||
|
std::stringstream ss;
|
||||||
void Reader::skipWhitespace() {
|
for (auto& section : sections) {
|
||||||
BasicParser::skipWhitespace();
|
ss << "[" << section.name << "]\n";
|
||||||
if (hasNext() && source[pos] == '#') {
|
for (const std::string& key : section.keys) {
|
||||||
skipLine();
|
ss << key << " = ";
|
||||||
if (hasNext() && is_whitespace(peek())) {
|
auto setting = handler.getSetting(section.name+"."+key);
|
||||||
skipWhitespace();
|
assert(setting != nullptr);
|
||||||
}
|
if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
|
||||||
}
|
ss << integer->get();
|
||||||
}
|
} else if (auto number = dynamic_cast<NumberSetting*>(setting)) {
|
||||||
|
ss << number->get();
|
||||||
void Reader::read() {
|
} else if (auto flag = dynamic_cast<FlagSetting*>(setting)) {
|
||||||
skipWhitespace();
|
ss << (flag->get() ? "true" : "false");
|
||||||
if (!hasNext()) {
|
} else if (auto string = dynamic_cast<StringSetting*>(setting)) {
|
||||||
return;
|
ss << util::escape(string->get());
|
||||||
}
|
}
|
||||||
readSection(nullptr);
|
ss << "\n";
|
||||||
}
|
}
|
||||||
|
ss << "\n";
|
||||||
inline bool is_numeric_type(fieldtype type) {
|
}
|
||||||
return type == fieldtype::ftint || type == fieldtype::ftfloat;
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Section::set(string name, double value) {
|
|
||||||
const Field* field = this->field(name);
|
|
||||||
if (field == nullptr) {
|
|
||||||
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
|
|
||||||
} else {
|
|
||||||
switch (field->type) {
|
|
||||||
case fieldtype::ftbool: *(bool*)(field->ptr) = fabs(value) > 0.0; break;
|
|
||||||
case fieldtype::ftint: *(int*)(field->ptr) = value; break;
|
|
||||||
case fieldtype::ftuint: *(uint*)(field->ptr) = value; break;
|
|
||||||
case fieldtype::ftfloat: *(float*)(field->ptr) = value; break;
|
|
||||||
case fieldtype::ftstring: *(string*)(field->ptr) = std::to_string(value); break;
|
|
||||||
default:
|
|
||||||
std::cerr << "error: type error for key '" << name << "'" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Section::set(std::string name, bool value) {
|
|
||||||
const Field* field = this->field(name);
|
|
||||||
if (field == nullptr) {
|
|
||||||
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
|
|
||||||
} else {
|
|
||||||
switch (field->type) {
|
|
||||||
case fieldtype::ftbool: *(bool*)(field->ptr) = value; break;
|
|
||||||
case fieldtype::ftint: *(int*)(field->ptr) = (int)value; break;
|
|
||||||
case fieldtype::ftuint: *(uint*)(field->ptr) = (uint)value; break;
|
|
||||||
case fieldtype::ftfloat: *(float*)(field->ptr) = (float)value; break;
|
|
||||||
case fieldtype::ftstring: *(string*)(field->ptr) = value ? "true" : "false"; break;
|
|
||||||
default:
|
|
||||||
std::cerr << "error: type error for key '" << name << "'" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Section::set(std::string name, std::string value) {
|
|
||||||
const Field* field = this->field(name);
|
|
||||||
if (field == nullptr) {
|
|
||||||
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
|
|
||||||
} else {
|
|
||||||
switch (field->type) {
|
|
||||||
case fieldtype::ftstring: *(string*)(field->ptr) = value; break;
|
|
||||||
default:
|
|
||||||
std::cerr << "error: type error for key '" << name << "'" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reader::readSection(Section* section /*nullable*/) {
|
|
||||||
while (hasNext()) {
|
|
||||||
skipWhitespace();
|
|
||||||
if (!hasNext()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char c = nextChar();
|
|
||||||
if (c == '[') {
|
|
||||||
string name = parseName();
|
|
||||||
Section* section = wrapper->section(name);
|
|
||||||
pos++;
|
|
||||||
readSection(section);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pos--;
|
|
||||||
string name = parseName();
|
|
||||||
expect('=');
|
|
||||||
c = peek();
|
|
||||||
if (is_digit(c)) {
|
|
||||||
number_u num;
|
|
||||||
if (parseNumber(1, num)) {
|
|
||||||
if (section)
|
|
||||||
section->set(name, (double)num.ival);
|
|
||||||
} else {
|
|
||||||
if (section)
|
|
||||||
section->set(name, num.fval);
|
|
||||||
}
|
|
||||||
} else if (c == '-' || c == '+') {
|
|
||||||
int sign = c == '-' ? -1 : 1;
|
|
||||||
pos++;
|
|
||||||
number_u num;
|
|
||||||
if (parseNumber(sign, num)) {
|
|
||||||
if (section)
|
|
||||||
section->set(name, (double)num.ival);
|
|
||||||
} else {
|
|
||||||
if (section)
|
|
||||||
section->set(name, num.fval);
|
|
||||||
}
|
|
||||||
} else if (is_identifier_start(c)) {
|
|
||||||
string identifier = parseName();
|
|
||||||
if (identifier == "true" || identifier == "false") {
|
|
||||||
bool flag = identifier == "true";
|
|
||||||
if (section) {
|
|
||||||
section->set(name, flag);
|
|
||||||
}
|
|
||||||
} else if (identifier == "inf") {
|
|
||||||
if (section) {
|
|
||||||
section->set(name, INFINITY);
|
|
||||||
}
|
|
||||||
} else if (identifier == "nan") {
|
|
||||||
if (section) {
|
|
||||||
section->set(name, NAN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (c == '"' || c == '\'') {
|
|
||||||
pos++;
|
|
||||||
string str = parseString(c);
|
|
||||||
if (section) {
|
|
||||||
section->set(name, str);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw error("feature is not supported");
|
|
||||||
}
|
|
||||||
expectNewLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
#ifndef CODERS_TOML_H_
|
|
||||||
#define CODERS_TOML_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "commons.h"
|
|
||||||
|
|
||||||
namespace toml {
|
|
||||||
enum class fieldtype {
|
|
||||||
ftbool,
|
|
||||||
ftint,
|
|
||||||
ftuint,
|
|
||||||
ftfloat,
|
|
||||||
ftstring,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Field {
|
|
||||||
fieldtype type;
|
|
||||||
void* ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Section {
|
|
||||||
std::unordered_map<std::string, Field> fields;
|
|
||||||
std::vector<std::string> keyOrder;
|
|
||||||
std::string name;
|
|
||||||
void add(std::string name, Field field);
|
|
||||||
public:
|
|
||||||
Section(std::string name);
|
|
||||||
void add(std::string name, bool* ptr);
|
|
||||||
void add(std::string name, int* ptr);
|
|
||||||
void add(std::string name, uint* ptr);
|
|
||||||
void add(std::string name, float* ptr);
|
|
||||||
void add(std::string name, std::string* ptr);
|
|
||||||
|
|
||||||
const Field* field(std::string name) const;
|
|
||||||
|
|
||||||
void set(std::string name, double value);
|
|
||||||
void set(std::string name, bool value);
|
|
||||||
void set(std::string name, std::string value);
|
|
||||||
|
|
||||||
std::string getName() const;
|
|
||||||
const std::vector<std::string>& keys() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Wrapper {
|
|
||||||
std::unordered_map<std::string, Section*> sections;
|
|
||||||
std::vector<std::string> keyOrder;
|
|
||||||
public:
|
|
||||||
~Wrapper();
|
|
||||||
Section& add(std::string section);
|
|
||||||
Section* section(std::string name);
|
|
||||||
|
|
||||||
std::string write() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Reader : public BasicParser {
|
|
||||||
Wrapper* wrapper;
|
|
||||||
void skipWhitespace() override;
|
|
||||||
void readSection(Section* section);
|
|
||||||
public:
|
|
||||||
Reader(Wrapper* wrapper, std::string file, std::string source);
|
|
||||||
void read();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CODERS_TOML_H_
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef CODERS_TOML_HPP_
|
||||||
|
#define CODERS_TOML_HPP_
|
||||||
|
|
||||||
|
#include "commons.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class SettingsHandler;
|
||||||
|
|
||||||
|
namespace toml {
|
||||||
|
std::string stringify(SettingsHandler& handler);
|
||||||
|
|
||||||
|
void parse(
|
||||||
|
SettingsHandler& handler,
|
||||||
|
const std::string& file,
|
||||||
|
const std::string& source
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CODERS_TOML_HPP_
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "wav.h"
|
#include "wav.hpp"
|
||||||
|
|
||||||
|
#include "../audio/audio.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -7,8 +9,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "../audio/audio.h"
|
|
||||||
|
|
||||||
bool is_big_endian() {
|
bool is_big_endian() {
|
||||||
uint32_t ui32_v = 0x01020304;
|
uint32_t ui32_v = 0x01020304;
|
||||||
char bytes[sizeof(uint32_t)];
|
char bytes[sizeof(uint32_t)];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef CODERS_WAV_H_
|
#ifndef CODERS_WAV_HPP_
|
||||||
#define CODERS_WAV_H_
|
#define CODERS_WAV_HPP_
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
@@ -13,4 +13,4 @@ namespace wav {
|
|||||||
extern audio::PCMStream* create_stream(const std::filesystem::path& file);
|
extern audio::PCMStream* create_stream(const std::filesystem::path& file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CODERS_WAV_H_
|
#endif // CODERS_WAV_HPP_
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#include "xml.h"
|
#include "xml.hpp"
|
||||||
|
|
||||||
|
#include "../util/stringutil.hpp"
|
||||||
|
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "../util/stringutil.h"
|
|
||||||
|
|
||||||
using namespace xml;
|
using namespace xml;
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ bool Attribute::asBool() const {
|
|||||||
glm::vec2 Attribute::asVec2() const {
|
glm::vec2 Attribute::asVec2() const {
|
||||||
size_t pos = text.find(',');
|
size_t pos = text.find(',');
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
throw std::runtime_error("invalid vec2 value "+escape_string(text));
|
return glm::vec2(util::parse_double(text, 0, text.length()));
|
||||||
}
|
}
|
||||||
return glm::vec2(
|
return glm::vec2(
|
||||||
util::parse_double(text, 0, pos),
|
util::parse_double(text, 0, pos),
|
||||||
@@ -48,11 +49,11 @@ glm::vec2 Attribute::asVec2() const {
|
|||||||
glm::vec3 Attribute::asVec3() const {
|
glm::vec3 Attribute::asVec3() const {
|
||||||
size_t pos1 = text.find(',');
|
size_t pos1 = text.find(',');
|
||||||
if (pos1 == std::string::npos) {
|
if (pos1 == std::string::npos) {
|
||||||
throw std::runtime_error("invalid vec3 value "+escape_string(text));
|
return glm::vec3(util::parse_double(text, 0, text.length()));
|
||||||
}
|
}
|
||||||
size_t pos2 = text.find(',', pos1+1);
|
size_t pos2 = text.find(',', pos1+1);
|
||||||
if (pos2 == std::string::npos) {
|
if (pos2 == std::string::npos) {
|
||||||
throw std::runtime_error("invalid vec3 value "+escape_string(text));
|
throw std::runtime_error("invalid vec3 value "+util::quote(text));
|
||||||
}
|
}
|
||||||
return glm::vec3(
|
return glm::vec3(
|
||||||
util::parse_double(text, 0, pos1),
|
util::parse_double(text, 0, pos1),
|
||||||
@@ -65,15 +66,15 @@ glm::vec3 Attribute::asVec3() const {
|
|||||||
glm::vec4 Attribute::asVec4() const {
|
glm::vec4 Attribute::asVec4() const {
|
||||||
size_t pos1 = text.find(',');
|
size_t pos1 = text.find(',');
|
||||||
if (pos1 == std::string::npos) {
|
if (pos1 == std::string::npos) {
|
||||||
throw std::runtime_error("invalid vec4 value "+escape_string(text));
|
return glm::vec4(util::parse_double(text, 0, text.length()));
|
||||||
}
|
}
|
||||||
size_t pos2 = text.find(',', pos1+1);
|
size_t pos2 = text.find(',', pos1+1);
|
||||||
if (pos2 == std::string::npos) {
|
if (pos2 == std::string::npos) {
|
||||||
throw std::runtime_error("invalid vec4 value "+escape_string(text));
|
throw std::runtime_error("invalid vec4 value "+util::quote(text));
|
||||||
}
|
}
|
||||||
size_t pos3 = text.find(',', pos2+1);
|
size_t pos3 = text.find(',', pos2+1);
|
||||||
if (pos3 == std::string::npos) {
|
if (pos3 == std::string::npos) {
|
||||||
throw std::runtime_error("invalid vec4 value "+escape_string(text));
|
throw std::runtime_error("invalid vec4 value "+util::quote(text));
|
||||||
}
|
}
|
||||||
return glm::vec4(
|
return glm::vec4(
|
||||||
util::parse_double(text, 0, pos1),
|
util::parse_double(text, 0, pos1),
|
||||||
@@ -99,7 +100,7 @@ glm::vec4 Attribute::asColor() const {
|
|||||||
}
|
}
|
||||||
return glm::vec4(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
|
return glm::vec4(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("hex colors are only supported");
|
return asVec4() / 255.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +177,7 @@ const std::string& Document::getEncoding() const {
|
|||||||
return encoding;
|
return encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser(std::string filename, std::string source)
|
Parser::Parser(const std::string& filename, const std::string& source)
|
||||||
: BasicParser(filename, source) {
|
: BasicParser(filename, source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,8 +197,13 @@ xmlelement Parser::parseOpenTag() {
|
|||||||
if (peek() == '=') {
|
if (peek() == '=') {
|
||||||
nextChar();
|
nextChar();
|
||||||
skipWhitespace();
|
skipWhitespace();
|
||||||
expect('"');
|
|
||||||
attrtext = parseString('"');
|
char quote = peek();
|
||||||
|
if (quote != '\'' && quote != '"') {
|
||||||
|
throw error("string literal expected");
|
||||||
|
}
|
||||||
|
skip(1);
|
||||||
|
attrtext = parseString(quote);
|
||||||
}
|
}
|
||||||
node->set(attrname, attrtext);
|
node->set(attrname, attrtext);
|
||||||
}
|
}
|
||||||
@@ -377,7 +383,7 @@ static void stringifyElement(
|
|||||||
auto attr = entry.second;
|
auto attr = entry.second;
|
||||||
ss << attr.getName();
|
ss << attr.getName();
|
||||||
if (!attr.getText().empty()) {
|
if (!attr.getText().empty()) {
|
||||||
ss << "=" << escape_string(attr.getText());
|
ss << "=" << util::escape(attr.getText());
|
||||||
}
|
}
|
||||||
if (count + 1 < int(attrs.size())) {
|
if (count + 1 < int(attrs.size())) {
|
||||||
ss << " ";
|
ss << " ";
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#ifndef CODERS_XML_H_
|
#ifndef CODERS_XML_HPP_
|
||||||
#define CODERS_XML_H_
|
#define CODERS_XML_HPP_
|
||||||
|
|
||||||
|
#include "commons.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -7,8 +9,6 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "commons.h"
|
|
||||||
|
|
||||||
namespace xml {
|
namespace xml {
|
||||||
class Node;
|
class Node;
|
||||||
class Attribute;
|
class Attribute;
|
||||||
@@ -118,7 +118,7 @@ namespace xml {
|
|||||||
std::string parseText();
|
std::string parseText();
|
||||||
std::string parseXMLName();
|
std::string parseXMLName();
|
||||||
public:
|
public:
|
||||||
Parser(std::string filename, std::string source);
|
Parser(const std::string& filename, const std::string& source);
|
||||||
|
|
||||||
xmldocument parse();
|
xmldocument parse();
|
||||||
};
|
};
|
||||||
@@ -141,4 +141,4 @@ namespace xml {
|
|||||||
extern xmldocument parse(std::string filename, std::string source);
|
extern xmldocument parse(std::string filename, std::string source);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CODERS_XML_H_
|
#endif // CODERS_XML_HPP_
|
||||||
@@ -1,13 +1,20 @@
|
|||||||
#ifndef SRC_CONSTANTS_H_
|
#ifndef CONSTANTS_HPP_
|
||||||
#define SRC_CONSTANTS_H_
|
#define CONSTANTS_HPP_
|
||||||
|
|
||||||
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "typedefs.h"
|
|
||||||
|
|
||||||
inline constexpr int ENGINE_VERSION_MAJOR = 0;
|
inline constexpr int ENGINE_VERSION_MAJOR = 0;
|
||||||
inline constexpr int ENGINE_VERSION_MINOR = 21;
|
inline constexpr int ENGINE_VERSION_MINOR = 21;
|
||||||
inline constexpr bool ENGINE_VERSION_INDEV = true;
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
inline constexpr bool ENGINE_DEBUG_BUILD = false;
|
||||||
|
#else
|
||||||
|
inline constexpr bool ENGINE_DEBUG_BUILD = true;
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
inline const std::string ENGINE_VERSION_STRING = "0.21";
|
inline const std::string ENGINE_VERSION_STRING = "0.21";
|
||||||
|
|
||||||
inline constexpr int BLOCK_AIR = 0;
|
inline constexpr int BLOCK_AIR = 0;
|
||||||
@@ -20,19 +27,21 @@ inline constexpr int CHUNK_D = 16;
|
|||||||
inline constexpr uint VOXEL_USER_BITS = 8;
|
inline constexpr uint VOXEL_USER_BITS = 8;
|
||||||
inline constexpr uint VOXEL_USER_BITS_OFFSET = sizeof(blockstate_t)*8-VOXEL_USER_BITS;
|
inline constexpr uint VOXEL_USER_BITS_OFFSET = sizeof(blockstate_t)*8-VOXEL_USER_BITS;
|
||||||
|
|
||||||
|
/// @brief pixel size of an item inventory icon
|
||||||
inline constexpr int ITEM_ICON_SIZE = 48;
|
inline constexpr int ITEM_ICON_SIZE = 48;
|
||||||
|
|
||||||
/* Chunk volume (count of voxels per Chunk) */
|
/// @brief chunk volume (count of voxels per Chunk)
|
||||||
inline constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
|
inline constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
|
||||||
|
|
||||||
/* BLOCK_VOID is block id used to mark non-existing voxel (voxel of missing chunk) */
|
/// @brief block id used to mark non-existing voxel (voxel of missing chunk)
|
||||||
inline constexpr blockid_t BLOCK_VOID = std::numeric_limits<blockid_t>::max();
|
inline constexpr blockid_t BLOCK_VOID = std::numeric_limits<blockid_t>::max();
|
||||||
|
/// @brief item id used to mark non-existing item (error)
|
||||||
inline constexpr itemid_t ITEM_VOID = std::numeric_limits<itemid_t>::max();
|
inline constexpr itemid_t ITEM_VOID = std::numeric_limits<itemid_t>::max();
|
||||||
|
/// @brief max number of block definitions possible
|
||||||
inline constexpr blockid_t MAX_BLOCKS = BLOCK_VOID;
|
inline constexpr blockid_t MAX_BLOCKS = BLOCK_VOID;
|
||||||
|
|
||||||
inline constexpr uint vox_index(uint x, uint y, uint z, uint w=CHUNK_W, uint d=CHUNK_D) {
|
inline constexpr uint vox_index(uint x, uint y, uint z, uint w=CHUNK_W, uint d=CHUNK_D) {
|
||||||
return (y * d + z) * w + x;
|
return (y * d + z) * w + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::string SHADERS_FOLDER = "shaders";
|
inline const std::string SHADERS_FOLDER = "shaders";
|
||||||
@@ -41,4 +50,4 @@ inline const std::string FONTS_FOLDER = "fonts";
|
|||||||
inline const std::string LAYOUTS_FOLDER = "layouts";
|
inline const std::string LAYOUTS_FOLDER = "layouts";
|
||||||
inline const std::string SOUNDS_FOLDER = "sounds";
|
inline const std::string SOUNDS_FOLDER = "sounds";
|
||||||
|
|
||||||
#endif // SRC_CONSTANTS_H_
|
#endif // CONSTANTS_HPP_
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
#include "Content.h"
|
#include "Content.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "../voxels/Block.h"
|
#include "../voxels/Block.hpp"
|
||||||
#include "../items/ItemDef.h"
|
#include "../items/ItemDef.hpp"
|
||||||
|
|
||||||
#include "ContentPack.h"
|
#include "ContentPack.hpp"
|
||||||
#include "../logic/scripting/scripting.h"
|
#include "../logic/scripting/scripting.hpp"
|
||||||
|
|
||||||
ContentBuilder::~ContentBuilder() {}
|
ContentBuilder::~ContentBuilder() {}
|
||||||
|
|
||||||
@@ -155,7 +155,14 @@ Content::Content(
|
|||||||
drawGroups(std::move(drawGroups))
|
drawGroups(std::move(drawGroups))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Content::~Content() {}
|
Content::~Content() {
|
||||||
|
for (auto& entry : blockDefs) {
|
||||||
|
delete entry.second;
|
||||||
|
}
|
||||||
|
for (auto& entry : itemDefs) {
|
||||||
|
delete entry.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Block* Content::findBlock(std::string id) const {
|
Block* Content::findBlock(std::string id) const {
|
||||||
auto found = blockDefs.find(id);
|
auto found = blockDefs.find(id);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef CONTENT_CONTENT_H_
|
#ifndef CONTENT_CONTENT_HPP_
|
||||||
#define CONTENT_CONTENT_H_
|
#define CONTENT_CONTENT_HPP_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -7,8 +7,8 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.hpp"
|
||||||
#include "../voxels/Block.h"
|
#include "../voxels/Block.hpp"
|
||||||
|
|
||||||
using DrawGroups = std::set<ubyte>;
|
using DrawGroups = std::set<ubyte>;
|
||||||
|
|
||||||
@@ -146,4 +146,4 @@ public:
|
|||||||
const std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>>& getPacks() const;
|
const std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>>& getPacks() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTENT_CONTENT_H_
|
#endif // CONTENT_CONTENT_HPP_
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
#include "ContentLUT.h"
|
#include "ContentLUT.hpp"
|
||||||
|
|
||||||
|
#include "Content.hpp"
|
||||||
|
#include "../constants.hpp"
|
||||||
|
#include "../files/files.hpp"
|
||||||
|
#include "../coders/json.hpp"
|
||||||
|
#include "../voxels/Block.hpp"
|
||||||
|
#include "../items/ItemDef.hpp"
|
||||||
|
#include "../data/dynamic.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "Content.h"
|
|
||||||
#include "../constants.h"
|
|
||||||
#include "../files/files.h"
|
|
||||||
#include "../coders/json.h"
|
|
||||||
#include "../voxels/Block.h"
|
|
||||||
#include "../items/ItemDef.h"
|
|
||||||
|
|
||||||
#include "../data/dynamic.h"
|
|
||||||
|
|
||||||
ContentLUT::ContentLUT(const Content* content, size_t blocksCount, size_t itemsCount) {
|
ContentLUT::ContentLUT(const Content* content, size_t blocksCount, size_t itemsCount) {
|
||||||
auto* indices = content->getIndices();
|
auto* indices = content->getIndices();
|
||||||
for (size_t i = 0; i < blocksCount; i++) {
|
for (size_t i = 0; i < blocksCount; i++) {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
#ifndef CONTENT_CONTENT_LUT_H_
|
#ifndef CONTENT_CONTENT_LUT_HPP_
|
||||||
#define CONTENT_CONTENT_LUT_H_
|
#define CONTENT_CONTENT_LUT_HPP_
|
||||||
|
|
||||||
|
#include "Content.hpp"
|
||||||
|
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
#include "../constants.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../constants.h"
|
|
||||||
|
|
||||||
#include "Content.h"
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
struct contententry {
|
struct contententry {
|
||||||
@@ -93,4 +93,4 @@ public:
|
|||||||
std::vector<contententry> getMissingContent() const;
|
std::vector<contententry> getMissingContent() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTENT_CONTENT_LUT_H_
|
#endif // CONTENT_CONTENT_LUT_HPP_
|
||||||
@@ -1,4 +1,17 @@
|
|||||||
#include "ContentLoader.h"
|
#include "ContentLoader.hpp"
|
||||||
|
|
||||||
|
#include "Content.hpp"
|
||||||
|
#include "ContentPack.hpp"
|
||||||
|
#include "../coders/json.hpp"
|
||||||
|
#include "../core_defs.hpp"
|
||||||
|
#include "../data/dynamic.hpp"
|
||||||
|
#include "../debug/Logger.hpp"
|
||||||
|
#include "../files/files.hpp"
|
||||||
|
#include "../items/ItemDef.hpp"
|
||||||
|
#include "../logic/scripting/scripting.hpp"
|
||||||
|
#include "../typedefs.hpp"
|
||||||
|
#include "../util/listutil.hpp"
|
||||||
|
#include "../voxels/Block.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -6,21 +19,10 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "Content.h"
|
|
||||||
#include "../items/ItemDef.h"
|
|
||||||
#include "../util/listutil.h"
|
|
||||||
#include "../voxels/Block.h"
|
|
||||||
#include "../files/files.h"
|
|
||||||
#include "../coders/json.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../core_defs.h"
|
|
||||||
#include "../data/dynamic.h"
|
|
||||||
|
|
||||||
#include "ContentPack.h"
|
|
||||||
#include "../logic/scripting/scripting.h"
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
static debug::Logger logger("content-loader");
|
||||||
|
|
||||||
ContentLoader::ContentLoader(ContentPack* pack) : pack(pack) {
|
ContentLoader::ContentLoader(ContentPack* pack) : pack(pack) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +102,6 @@ void ContentLoader::fixPackIndices() {
|
|||||||
|
|
||||||
if (modified){
|
if (modified){
|
||||||
// rewrite modified json
|
// rewrite modified json
|
||||||
std::cout << indexFile << std::endl;
|
|
||||||
files::write_json(indexFile, root.get());
|
files::write_json(indexFile, root.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,11 +322,11 @@ BlockMaterial ContentLoader::loadBlockMaterial(fs::path file, std::string full)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentLoader::load(ContentBuilder& builder) {
|
void ContentLoader::load(ContentBuilder& builder) {
|
||||||
std::cout << "-- loading pack [" << pack->id << "]" << std::endl;
|
logger.info() << "loading pack [" << pack->id << "]";
|
||||||
|
|
||||||
auto runtime = new ContentPackRuntime(*pack, scripting::create_pack_environment(*pack));
|
auto runtime = new ContentPackRuntime(*pack, scripting::create_pack_environment(*pack));
|
||||||
builder.add(runtime);
|
builder.add(runtime);
|
||||||
env = runtime->getEnvironment()->getId();
|
env = runtime->getEnvironment();
|
||||||
ContentPackStats& stats = runtime->getStatsWriteable();
|
ContentPackStats& stats = runtime->getStatsWriteable();
|
||||||
|
|
||||||
fixPackIndices();
|
fixPackIndices();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CONTENT_CONTENT_LOADER_H_
|
#ifndef CONTENT_CONTENT_LOADER_HPP_
|
||||||
#define CONTENT_CONTENT_LOADER_H_
|
#define CONTENT_CONTENT_LOADER_HPP_
|
||||||
|
|
||||||
#include "../voxels/Block.h"
|
#include "../voxels/Block.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@@ -18,7 +18,7 @@ namespace dynamic {
|
|||||||
|
|
||||||
class ContentLoader {
|
class ContentLoader {
|
||||||
const ContentPack* pack;
|
const ContentPack* pack;
|
||||||
int env = 0;
|
scriptenv env;
|
||||||
|
|
||||||
void loadBlock(Block& def, std::string full, std::string name);
|
void loadBlock(Block& def, std::string full, std::string name);
|
||||||
void loadCustomBlockModel(Block& def, dynamic::Map* primitives);
|
void loadCustomBlockModel(Block& def, dynamic::Map* primitives);
|
||||||
@@ -38,4 +38,4 @@ public:
|
|||||||
void load(ContentBuilder& builder);
|
void load(ContentBuilder& builder);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTENT_CONTENT_LOADER_H_
|
#endif // CONTENT_CONTENT_LOADER_HPP_
|
||||||