examples,os: add an os.asset module, use it to simplify code in examples/, by removing $if android { checks (#22281)

This commit is contained in:
Delyan Angelov 2024-09-22 16:04:05 +03:00 committed by GitHub
parent 64d1770cf1
commit cfa91d81d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 69 additions and 117 deletions

View file

@ -1,7 +1,7 @@
import gg import gg
import gx import gx
import math import math
import os import os.asset
import rand import rand
import time import time
@ -899,10 +899,6 @@ fn init(mut app App) {
fn main() { fn main() {
mut app := &App{} mut app := &App{}
app.new_game() app.new_game()
mut font_path := os.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf'))
$if android {
font_path = 'fonts/RobotoMono-Regular.ttf'
}
app.gg = gg.new_context( app.gg = gg.new_context(
bg_color: app.theme.bg_color bg_color: app.theme.bg_color
width: default_window_width width: default_window_width
@ -913,7 +909,7 @@ fn main() {
event_fn: on_event event_fn: on_event
init_fn: init init_fn: init
user_data: app user_data: app
font_path: font_path font_path: asset.get_path('../assets', 'fonts/RobotoMono-Regular.ttf')
) )
app.gg.run() app.gg.run()
} }

View file

@ -2,7 +2,6 @@
// This is a small V example that was based off of the fireworks example. // This is a small V example that was based off of the fireworks example.
// Written by Stefan Schroeder in 2021 for the v project examples. // Written by Stefan Schroeder in 2021 for the v project examples.
// See LICENSE for license information. // See LICENSE for license information.
import os
import gg import gg
import gx import gx
import math import math
@ -147,13 +146,7 @@ fn on_init(mut app App) {
fn main() { fn main() {
println("Press 'q' to quit.") println("Press 'q' to quit.")
mut font_path := os.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf'))
$if android {
font_path = 'fonts/RobotoMono-Regular.ttf'
}
mut app := &App{} mut app := &App{}
app.gg = gg.new_context( app.gg = gg.new_context(
width: design_size width: design_size
height: design_size height: design_size
@ -163,8 +156,6 @@ fn main() {
frame_fn: on_frame frame_fn: on_frame
event_fn: on_event event_fn: on_event
init_fn: on_init init_fn: on_init
font_path: font_path
) )
app.gg.run() app.gg.run()
} }

View file

@ -1,4 +1,3 @@
import os
import objects import objects
import gg import gg
import gx import gx
@ -94,14 +93,8 @@ fn (mut app App) resize() {
} }
fn main() { fn main() {
mut font_path := os.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf'))
$if android {
font_path = 'fonts/RobotoMono-Regular.ttf'
}
mut app := &App{} mut app := &App{}
app.ui = objects.get_params() app.ui = objects.get_params()
app.gg = gg.new_context( app.gg = gg.new_context(
width: app.ui.width width: app.ui.width
height: app.ui.height height: app.ui.height
@ -110,8 +103,6 @@ fn main() {
user_data: app user_data: app
frame_fn: on_frame frame_fn: on_frame
event_fn: on_event event_fn: on_event
font_path: font_path
) )
app.gg.run() app.gg.run()
} }

View file

@ -2,11 +2,11 @@ module main
import gg import gg
import gx import gx
import os
import time import time
import math import math
import rand import rand
import neuroevolution import neuroevolution
import os.asset
const win_width = 500 const win_width = 500
const win_height = 512 const win_height = 512
@ -173,10 +173,6 @@ fn (mut app App) update() {
fn main() { fn main() {
mut app := &App{} mut app := &App{}
mut font_path := os.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf'))
$if android {
font_path = 'fonts/RobotoMono-Regular.ttf'
}
app.gg = gg.new_context( app.gg = gg.new_context(
bg_color: gx.white bg_color: gx.white
width: win_width width: win_width
@ -187,7 +183,7 @@ fn main() {
event_fn: on_event event_fn: on_event
user_data: app user_data: app
init_fn: app.init_images_wrapper init_fn: app.init_images_wrapper
font_path: font_path font_path: asset.get_path('../assets', 'fonts/RobotoMono-Regular.ttf')
) )
app.nv = neuroevolution.Generations{ app.nv = neuroevolution.Generations{
population: 50 population: 50
@ -210,21 +206,10 @@ fn (mut app App) init_images_wrapper() {
} }
fn (mut app App) init_images() ! { fn (mut app App) init_images() ! {
$if android { app.background = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/background.png')!)!
background := os.read_apk_asset('img/background.png')! app.bird = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/bird.png')!)!
app.background = app.gg.create_image_from_byte_array(background)! app.pipetop = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/pipetop.png')!)!
bird := os.read_apk_asset('img/bird.png')! app.pipebottom = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/pipebottom.png')!)!
app.bird = app.gg.create_image_from_byte_array(bird)!
pipetop := os.read_apk_asset('img/pipetop.png')!
app.pipetop = app.gg.create_image_from_byte_array(pipetop)!
pipebottom := os.read_apk_asset('img/pipebottom.png')!
app.pipebottom = app.gg.create_image_from_byte_array(pipebottom)!
} $else {
app.background = app.gg.create_image(os.resource_abs_path('assets/img/background.png'))!
app.bird = app.gg.create_image(os.resource_abs_path('assets/img/bird.png'))!
app.pipetop = app.gg.create_image(os.resource_abs_path('assets/img/pipetop.png'))!
app.pipebottom = app.gg.create_image(os.resource_abs_path('assets/img/pipebottom.png'))!
}
} }
fn frame(app &App) { fn frame(app &App) {

View file

@ -2,7 +2,7 @@ module main
import gg import gg
import gx import gx
import os import os.asset
import math import math
const win_width = 600 const win_width = 600
@ -62,10 +62,6 @@ mut:
fn main() { fn main() {
mut app := &App{} mut app := &App{}
mut font_path := os.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf'))
$if android {
font_path = 'fonts/RobotoMono-Regular.ttf'
}
app.gg = gg.new_context( app.gg = gg.new_context(
width: win_width width: win_width
height: win_height height: win_height
@ -74,7 +70,8 @@ fn main() {
user_data: app user_data: app
bg_color: bg_color bg_color: bg_color
frame_fn: frame frame_fn: frame
font_path: font_path // window_user_ptr: ctx font_path: asset.get_path('../assets', 'fonts/RobotoMono-Regular.ttf')
// window_user_ptr: ctx
// native_rendering: true // native_rendering: true
) )
app.gg.run() app.gg.run()

View file

@ -2,7 +2,7 @@ module main
import gg import gg
import gx import gx
import os import os.asset
const win_width = 600 const win_width = 600
const win_height = 300 const win_height = 300
@ -23,20 +23,12 @@ fn main() {
window_title: 'Rectangles' window_title: 'Rectangles'
frame_fn: frame frame_fn: frame
user_data: app user_data: app
init_fn: init_images
) )
mut logo_path := os.resource_abs_path(os.join_path('..', 'assets', 'logo.png')) logo_path := asset.get_path('../assets', 'logo.png')
$if android {
logo_path = 'logo.png'
}
app.image = app.gg.create_image(logo_path)!.id app.image = app.gg.create_image(logo_path)!.id
app.gg.run() app.gg.run()
} }
fn init_images(mut app App) {
// app.image = gg.create_image('logo.png')
}
fn frame(app &App) { fn frame(app &App) {
app.gg.begin() app.gg.begin()
app.draw() app.draw()

View file

@ -1,6 +1,6 @@
import gg import gg
import gx import gx
import os import os.asset
import sokol.sgl import sokol.sgl
pub struct Window { pub struct Window {
@ -10,11 +10,7 @@ pub mut:
} }
pub fn (mut window Window) init() { pub fn (mut window Window) init() {
image_path := $if android { image_path := asset.get_path('../assets', 'logo.png')
'logo.png'
} $else {
os.resource_abs_path('../assets/logo.png')
}
window.img = window.ctx.create_image(image_path) or { panic(err) } window.img = window.ctx.create_image(image_path) or { panic(err) }
} }

View file

@ -1,6 +1,6 @@
module main module main
import os import os.asset
import gg import gg
import gx import gx
import rand import rand
@ -78,10 +78,7 @@ fn main() {
} }
fn init_images(mut app App) { fn init_images(mut app App) {
mut logo_path := os.resource_abs_path(os.join_path('..', 'assets', 'logo.png')) logo_path := asset.get_path('../assets', 'logo.png')
$if android {
logo_path = 'logo.png'
}
app.image = app.gg.create_image(logo_path) or { panic(err) } app.image = app.gg.create_image(logo_path) or { panic(err) }
} }

View file

@ -1,52 +1,24 @@
module obj module obj
import os import os
import os.asset
// read a file as single lines // read a file as single lines
pub fn read_lines_from_file(file_path string) []string { pub fn read_lines_from_file(file_path string) []string {
mut path := '' if os.exists(file_path) {
mut rows := []string{} return os.read_lines(file_path) or { [] }
$if android {
path = 'models/' + file_path
bts := os.read_apk_asset(path) or {
eprintln('File [${path}] NOT FOUND!')
return rows
}
rows = bts.bytestr().split_into_lines()
} $else {
path = if os.exists(file_path) {
file_path
} else {
os.resource_abs_path('assets/models/${file_path}')
}
rows = os.read_lines(path) or {
eprintln('File [${path}] NOT FOUND! file_path: ${file_path}')
return rows
}
} }
return rows return read_bytes_from_file(file_path).bytestr().split_into_lines()
} }
// read a file as []u8 // read a file as []u8
pub fn read_bytes_from_file(file_path string) []u8 { pub fn read_bytes_from_file(file_path string) []u8 {
mut path := '' if os.exists(file_path) {
mut buffer := []u8{} return os.read_bytes(file_path) or { [] }
$if android { }
path = 'models/' + file_path mpath := 'models/${file_path}'
buffer = os.read_apk_asset(path) or { return asset.read_bytes('assets', mpath) or {
eprintln('Texture file: [${path}] NOT FOUND!') eprintln('Model file NOT FOUND: `${mpath}`')
exit(0) exit(0)
}
} $else {
path = if os.exists(file_path) {
file_path
} else {
os.resource_abs_path('assets/models/${file_path}')
}
buffer = os.read_bytes(path) or {
eprintln('Texture file: [${path}] NOT FOUND!')
exit(0)
}
} }
return buffer
} }

View file

@ -3,7 +3,7 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module main module main
import os import os.asset
import rand import rand
import time import time
import gx import gx
@ -157,10 +157,6 @@ fn frame(mut game Game) {
fn main() { fn main() {
mut game := &Game{} mut game := &Game{}
mut fpath := os.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf'))
$if android {
fpath = 'fonts/RobotoMono-Regular.ttf'
}
game.gg = gg.new_context( game.gg = gg.new_context(
bg_color: gx.white bg_color: gx.white
width: win_width width: win_width
@ -170,7 +166,8 @@ fn main() {
user_data: game user_data: game
frame_fn: frame frame_fn: frame
event_fn: on_event event_fn: on_event
font_path: fpath // wait_events: true font_path: asset.get_path('../assets', 'fonts/RobotoMono-Regular.ttf')
// wait_events: true
) )
game.init_game() game.init_game()
game.gg.run() // Run the render loop in the main thread game.gg.run() // Run the render loop in the main thread

11
vlib/os/asset/README.md Normal file
View file

@ -0,0 +1,11 @@
# Asset
The `asset` module provides a cross platform way to read assets, without cluttering
the user code with comptime conditionals, like `$if ios {` or `$if android {` etc.
Currently it supports Android assets, and desktop applications, that do not use
archived/zipped files, but could be extended to support archived files too in the future.
It relies on the assumption that each platform has a way to either read files, relative
to the location of the executable, or a platform specific way, to package all asset files
into the application archive/package/executable, that is then distributed to the end users.

27
vlib/os/asset/asset.v Normal file
View file

@ -0,0 +1,27 @@
module asset
import os
// get_path returns a platform specific path, based on the given asset base folder and relative path
// of a resource in it. On desktop systems, it returns a path relative to the location of the executable.
// On Android, it will return just the relative_path segment, allowing you to later use os.read_apk_asset
// to read from it.
pub fn get_path(base_folder string, relative_path string) string {
$if android {
return relative_path
} $else {
return os.resource_abs_path(os.join_path(base_folder, relative_path))
}
}
// read_bytes will read all of the given asset, specified by its base_folder and relative path in it.
// On Android, it will use os.read_apk_asset, relying that the asset base folder has been prepared, and
// prepackaged inside your APK. On desktop systems, it will use the base_folder and relative_path, to
// locate the file, in a way, that is relative to the executable.
pub fn read_bytes(base_folder string, relative_path string) ![]u8 {
$if android {
return os.read_apk_asset(get_path(base_folder, relative_path))
} $else {
return os.read_bytes(get_path(base_folder, relative_path))
}
}