gcores ~/apps/Menu branch first commit

This commit is contained in:
cpi
2019-07-16 03:40:14 +00:00
parent 2d75a8d65d
commit 45737f787c
2136 changed files with 214 additions and 17128 deletions

View File

@@ -1,52 +0,0 @@
/*
set_text(render void, text. char, color uint32)
*/
class game+, control+, button {
inherit game::control = super;
private import lib::sdl2;
struct button {
tex texture;
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
inline set_text(render void, text. char, color uint32 = 0xff000000) {
this.tex->init(
global::uni_font->create_tex(render, text, color));
}
func draw(render void) {
var rect SDL_Rect = this->get_rect();
SDL_SetRenderDrawColor(render, 245, 245, 245, 0xff);
SDL_RenderFillRect(render, &rect);
if this->has_focus() {
SDL_SetRenderDrawColor(render, 0, 162, 232, 0xff);
else
SDL_SetRenderDrawColor(render, 127, 127, 127, 0xff);
}
SDL_RenderDrawRect(render, &rect);
if this.tex->get_texture() ~= null {
var width int = this.tex->get_width();
var height int = this.tex->get_height();
rect.x++;
rect.y++;
rect.w -= 2;
rect.h -= 2;
this.tex->draw2(render,
rect.x + (rect.w - width) / 2,
rect.y + (rect.h - height) / 2, width, height);
}
}
}

View File

@@ -1,75 +0,0 @@
/*
set_text_color(color uint32)
set_text(render void, text. char, color uint32)
get_text() .char
get_keybd_cb() void
*/
class game+, control+, edit {
inherit game::control = super;
private import lib::sdl2;
private alias string = std::string;
struct edit {
tex texture;
str string;
text_color uint32;
}
func constructor() {
constructor(this);
this.text_color = 0xff000000;
}
func destructor() {
destructor(this);
}
inline set_text_color(color uint32) {
this.text_color = color;
}
inline set_text(render void, text. char) {
this.str->set(text);
this.tex->init(
global::uni_font->create_tex(render, text, this.text_color));
}
inline get_text() .char {
return this.str->ptr();
}
inline get_keybd_cb() void {
return lambda(text. char, this.edit) [
this->set_text(this->get_window()->get_render(), text);
];
}
func draw(render void) {
define {
TEXT_GAP = 3;
}
var rect SDL_Rect = this->get_rect();
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
SDL_RenderFillRect(render, &rect);
if this->has_focus() {
SDL_SetRenderDrawColor(render, 0, 162, 232, 0xff);
else
SDL_SetRenderDrawColor(render, 127, 127, 127, 0xff);
}
SDL_RenderDrawRect(render, &rect);
if this.tex->get_texture() ~= null {
var width int = this.tex->get_width();
var height int = this.tex->get_height();
var max_width int = rect.w - (TEXT_GAP * 2);
if width > max_width;
width = max_width;
this.tex->draw2(render, rect.x + TEXT_GAP, rect.y + (rect.h - height) / 2, width, height);
}
}
}

View File

@@ -1,79 +0,0 @@
/*
set_normal_image(render void, filename. char) bool
set_hover_image(render void, filename. char) bool
set_image(render void, filename. char) bool
set_outline_size(size int)
get_outline_size() int
*/
class game+, control+, image_button {
inherit game::control = super;
private import lib::sdl2;
struct image_button {
normal texture;
hover texture;
image texture;
outline_size int;
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
inline set_normal_image(render void, filename. char) bool {
if func = this.normal->load_file(render, filename) {
this->set_size(
this.normal->get_width(),
this.normal->get_height());
}
}
inline set_hover_image(render void, filename. char) bool {
return this.hover->load_file(render, filename);
}
inline set_image(render void, filename. char) bool {
return this.image->load_file(render, filename);
}
inline set_outline_size(size int) {
this.outline_size = size;
}
inline get_outline_size() int {
return this.outline_size;
}
func draw(render void) {
var rect SDL_Rect = this->get_rect();
if this->has_focus() {
this.hover->draw(render, rect.x, rect.y);
else
this.normal->draw(render, rect.x, rect.y);
}
if this.outline_size {
rect.x += this.outline_size;
rect.y += this.outline_size;
rect.w -= this.outline_size * 2;
rect.h -= this.outline_size * 2;
}
var width int = this.image->get_width();
var height int = this.image->get_height();
if width > rect.w;
width = rect.w;
if height > rect.h;
height = rect.h;
this.image->draw3(render,
rect.x + (rect.w - width) / 2,
rect.y + (rect.h - height) / 2, width, height);
}
}

View File

@@ -1,35 +0,0 @@
/*
set_text(render void, text. char, color uint32) bool
*/
class game+, control+, label {
inherit game::control = super;
private import lib::sdl2;
struct label {
tex texture;
}
func constructor() {
constructor(this); }
func destructor() {
destructor(this); }
func set_text(render void, text. char, color uint32 = 0xff000000) bool {
if func = this.tex->init(global::uni_font->create_tex(render, text, color)) {
this->set_size(
this.tex->get_width(),
this.tex->get_height());
}
}
func draw(render void) {
this.tex->draw(render,
this->get_x(),
this->get_y());
}
}

View File

@@ -1,158 +0,0 @@
/*
set_callback(on_select void, on_close void, arg void)
add_menu(render void, id int, title. char)
*/
class game+, control+, popup_menu {
inherit game::control = super;
private import rt::c, lib::sdl2;
private alias
string = std::string,
vector = std::vector;
class menu {
struct menu {
white_title texture;
black_title texture;
id int;
}
func constructor() {
constructor(this);
this.id = -1;
}
func destructor() {
destructor(this);
}
}
struct popup_menu {
menus vector<menu>;
input_delay repeat;
input_lock norepeat;
on_select void;
on_close void;
arg void;
cursor int;
}
func constructor() {
memset(this, 0, sizeof(popup_menu));
constructor(this);
}
func destructor() {
destructor(this);
}
define {
MENU_GAP = 12;
MENU_HEIGHT = 25;
}
func init(render void) bool {
this.input_delay->init(300, -10, 20);
return true;
}
/*
on_select = lambda(id int, arg void) [
];
on_close = lambda(arg void) [
];
*/
inline set_callback(on_select void, on_close void, arg void) {
this.on_select = on_select;
this.on_close = on_close;
this.arg = arg;
}
func add_menu(render void, id int, title. char) {
var menu. menu = this.menus->new();
menu.white_title->init(
global::uni_font->create_tex(render, title, 0xffffffff));
menu.black_title->init(
global::uni_font->create_tex(render, title, 0xff000000));
menu.id = id;
var width int = menu.black_title->get_width() + (MENU_GAP * 2);
if this->get_width() < width;
this->set_width(width);
this->set_height(this.menus->count() * MENU_HEIGHT + 2);
}
func update(render void) {
var state. uint8 = SDL_GetKeyboardState(null);
if state[CPI_SCANCODE_UP] {
if this.input_delay->do() {
if this.cursor;
this.cursor--;
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_DOWN];
if this.input_delay->do() {
if this.cursor < this.menus->count() - 1;
this.cursor++;
this.input_delay->undo();
}
else
this.input_delay->reset();
}
if state[CPI_SCANCODE_A] or
state[CPI_SCANCODE_B] or
state[CPI_SCANCODE_MENU] {
if this.input_lock->do() {
if state[CPI_SCANCODE_B] {
proto fn(id int, arg void);
fn[this.on_select](this.menus->at(this.cursor).id, this.arg);
}
{
proto fn(arg void);
fn[this.on_close](this.arg);
}
}
else
this.input_lock->set(false);
}
}
func draw(render void) {
var rect SDL_Rect = this->get_rect();
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
SDL_RenderFillRect(render, &rect);
SDL_SetRenderDrawColor(render, 0xcd, 0xcd, 0xcd, 0xff);
SDL_RenderDrawRect(render, &rect);
rect.x += 1;
rect.y += 1;
rect.w -= 2;
rect.h -= 2;
forvar index size_t = 0, count size_t = this.menus->count(); index < count; index++ {
var menu. menu = this.menus->at(index);
if this.cursor == index {
var sub_rect SDL_Rect;
sub_rect.x = rect.x;
sub_rect.y = rect.y;
sub_rect.w = rect.w;
sub_rect.h = MENU_HEIGHT;
SDL_SetRenderDrawColor(render, 0x00, 0xa2, 0xe8, 0xff);
SDL_RenderFillRect(render, &sub_rect);
menu.white_title->draw(render, rect.x + MENU_GAP,
rect.y + (MENU_HEIGHT - menu.white_title->get_height()) / 2);
else
menu.black_title->draw(render, rect.x + MENU_GAP,
rect.y + (MENU_HEIGHT - menu.black_title->get_height()) / 2);
}
rect.y += MENU_HEIGHT;
}
}
func wake() {
this.input_delay->reset(false);
this.input_lock->set(true);
}
}

View File

@@ -1,38 +0,0 @@
// template
class game+, control+, temp {
inherit game::control = super;
private import lib::sdl2;
struct temp {
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
func init(render void) bool {
return true;
}
func update(render void) {
this.super->update(render);
}
func draw(render void) {
this.super->draw(render);
}
func wake() {
this.super->wake();
}
}

View File

@@ -1,41 +0,0 @@
module game+ {
private import lib::sdl2;
define {
CPI_WIDTH = 320;
CPI_HEIGHT = 240;
}
define {
CPI_SCANCODE_MENU = SDL_SCANCODE_ESCAPE;
CPI_SCANCODE_SELECT = SDL_SCANCODE_SPACE;
CPI_SCANCODE_START = SDL_SCANCODE_RETURN;
CPI_SCANCODE_A = SDL_SCANCODE_J;
CPI_SCANCODE_B = SDL_SCANCODE_K;
CPI_SCANCODE_X = SDL_SCANCODE_U;
CPI_SCANCODE_Y = SDL_SCANCODE_I;
CPI_SCANCODE_UP = SDL_SCANCODE_UP;
CPI_SCANCODE_DOWN = SDL_SCANCODE_DOWN;
CPI_SCANCODE_LEFT = SDL_SCANCODE_LEFT;
CPI_SCANCODE_RIGHT = SDL_SCANCODE_RIGHT;
CPI_SCANCODE_LK1 = SDL_SCANCODE_H;
CPI_SCANCODE_LK2 = SDL_SCANCODE_Y;
CPI_SCANCODE_LK3 = SDL_SCANCODE_UNKNOWN; // ???
CPI_SCANCODE_LK4 = SDL_SCANCODE_O;
CPI_SCANCODE_LK5 = SDL_SCANCODE_L;
CPI_SCANCODE_SHIFT_SELECT = SDL_SCANCODE_KP_MINUS;
CPI_SCANCODE_SHIFT_START = SDL_SCANCODE_KP_PLUS;
CPI_SCANCODE_SHIFT_A = SDL_SCANCODE_H; // CPI_SCANCODE_LK1
CPI_SCANCODE_SHIFT_B = SDL_SCANCODE_L; // CPI_SCANCODE_LK5
CPI_SCANCODE_SHIFT_X = SDL_SCANCODE_Y; // CPI_SCANCODE_LK2
CPI_SCANCODE_SHIFT_Y = SDL_SCANCODE_O; // CPI_SCANCODE_LK4
}
define {
CPI_BACKLIGHT = "/proc/driver/backlight";
CPI_BATTERY = "/sys/class/power_supply/axp20x-battery/uevent";
}
}

View File

@@ -1,231 +0,0 @@
class game+, control+ {
private import rt::c, lib::sdl2;
private alias vector = std::vector;
struct control {
struct callback {
update void;
draw void;
wake void;
destructor void;
}
parent. scene;
parent_control. control;
controls vector<void>;
focus_control. control;
popup. control;
closing_popup. control;
pending_popup. control;
x int;
y int;
width int;
height int;
enable bool;
visible bool;
focus bool;
}
func constructor() {
memset(this, 0, sizeof(control));
this.enable = true;
this.visible = true;
constructor(this);
}
func destructor() {
if this.popup ~= null;
this->free_control(this.popup);
if this.closing_popup ~= null;
this->free_control(this.closing_popup);
if this.pending_popup ~= null;
this->free_control(this.pending_popup);
forvar count size_t = this.controls->count(); count;;
this->free_control(.this.controls->at(--count));
destructor(this);
}
//
inline create_control<T>(x int, y int, width int = 0, height int = 0) .T {
func = this.parent->create_control<T>(x, y, width, height);
func->set_parent_control(this);
}
inline new_control<T>(x int, y int, width int = 0, height int = 0) .T {
this.controls->push_back(
func = this->create_control<T>(this.x + x, this.y + y, width, height));
}
inline free_control(control. control) {
this.parent->free_control(control);
}
// focus
func set_focus(control. control) {
var prev. control = this.focus_control;
if prev ~= null;
prev.focus = false;
this.focus_control = control, control.focus = true;
}
inline get_focus() .control {
return this.focus_control;
}
// popup
func close_popup() {
if this.popup ~= null {
this.closing_popup = this.popup;
this.popup = null;
// xxx
if this.callback.wake ~= null {
proto fn(this void);
fn[this.callback.wake](this);
}
}
}
func close_parent_popup() {
if this.parent_control == null {
this.parent->close_popup();
else
this.parent_control->close_popup();
}
}
func set_popup(control. control) {
if this.popup == null and this.closing_popup == null {
this.popup = control;
else
if this.pending_popup ~= null;
this->free_control(this.pending_popup);
this.pending_popup = control;
}
}
func has_popup() bool {
if this.popup ~= null or
this.closing_popup ~= null or
this.pending_popup ~= null {
return true;
}
return false;
}
//
func update(render void) {
proto fn(this void, render void);
if this.closing_popup ~= null;
this->free_control(this.closing_popup), this.closing_popup = null;
if this.pending_popup ~= null {
if this.popup ~= null;
this->free_control(this.popup);
this.popup = this.pending_popup;
this.pending_popup = null;
}
// xxx
if this.popup == null {
forvar count size_t = this.controls->count(); count; {
var control. control = .this.controls->at(--count);
if control.callback.update ~= null;
fn[control.callback.update](control, render);
}
else
var popup. control = this.popup;
if popup.callback.update ~= null;
fn[popup.callback.update](popup, render);
}
}
func draw(render void) {
proto fn(this void, render void);
forvar count size_t = this.controls->count(); count; {
var control. control = .this.controls->at(--count);
if control.callback.draw ~= null;
fn[control.callback.draw](control, render);
}
if this.popup ~= null {
var popup. control = this.popup;
if popup.callback.draw ~= null;
fn[popup.callback.draw](popup, render);
}
}
func wake() {
proto fn(this void);
forvar count size_t = this.controls->count(); count; {
var control. control = .this.controls->at(--count);
if control.callback.wake ~= null;
fn[control.callback.wake](control);
}
if this.popup ~= null {
var popup. control = this.popup;
if popup.callback.wake ~= null;
fn[popup.callback.wake](popup);
}
}
//
inline set_parent(scene. scene) {
this.parent = scene;
}
inline get_parent() .scene {
return this.parent;
}
inline get_parent_t<T>() .T {
return this.parent;
}
inline set_parent_control(control. control) {
this.parent_control = control;
}
inline get_parent_control() .control {
return this.parent_control;
}
inline get_parent_control_t<T>() .T {
return this.parent_control;
}
inline get_window() .window {
return this.parent->get_window();
}
//
inline set_x(x int) { this.x = x; }
inline set_y(y int) { this.y = y; }
inline set_pos(x int, y int) { this.x = x, this.y = y; }
inline set_width(width int) { this.width = width; }
inline set_height(height int) { this.height = height; }
inline set_size(width int, height int) {
this.width = width,
this.height = height;
}
inline get_x() int { return this.x; }
inline get_y() int { return this.y; }
inline get_width() int { return this.width; }
inline get_height() int { return this.height; }
inline get_right() int { return this.x + this.width; }
inline get_bottom() int { return this.y + this.height; }
inline get_rect() SDL_Rect {
func.x = this.x,
func.y = this.y,
func.w = this.width,
func.h = this.height;
}
inline has_focus() bool { return this.focus; }
}

View File

@@ -1,80 +0,0 @@
// SDL_GetTicks: This value wraps if the program runs for more than ~49 days.
class game+, delay {
private import lib::sdl2;
struct delay {
duration uint32;
t uint32;
last_t uint32;
done bool;
}
inline init(duration uint32, done bool = false) {
this.duration = duration;
this.t = 0;
this.last_t = 0;
this.done = done;
}
inline reset() {
this.t = 0;
this.last_t = 0;
this.done = false;
}
inline done() {
this.done = true;
}
inline done?() bool {
return this.done;
}
inline do() bool {
if !this.done {
this.last_t = SDL_GetTicks();
if !this.t;
this.t = this.last_t + this.duration;
if this.t > this.last_t;
return false;
this.done = true;
}
return true;
}
inline undo() {
this.last_t = SDL_GetTicks();
this.t = this.last_t + this.duration;
this.done = false;
}
//
inline get_duration() uint32 {
return this.duration;
}
inline set_duration(duration uint32) {
this.duration = duration;
}
inline inc_duration(inc int32) {
this.duration += inc;
}
inline get_remain_t() uint32 {
return this.t - this.last_t;
}
inline get_per<T>(x T) T {
return (float(this->get_remain_t()) / this.duration) * x;
}
inline get_per_r<T>(x T) T {
return x - this->get_per<T>(x);
}
}

View File

@@ -1,87 +0,0 @@
class game+, fadeio {
private import rt::c, lib::sdl2;
struct fadeio {
delay delay;
texture texture;
rect SDL_Rect;
render void;
done bool;
r uint8;
g uint8;
b uint8;
}
func constructor() {
memset(this, 0, sizeof(fadeio));
constructor(this);
}
func destructor() {
destructor(this);
}
//
inline init(wnd. window, duration uint32) {
this.delay->init(duration);
this.render = wnd->get_render();
wnd->get_size(&this.rect.w, &this.rect.h);
}
//
inline set_color(r uint8, g uint8, b uint8) {
this.texture->destroy();
this.r = r;
this.g = g;
this.b = b;
}
inline set_texture(texture void, auto_destroy bool = true) bool {
if func = this.texture->init(texture, auto_destroy);
this.texture->set_blend_mode(SDL_BLENDMODE_BLEND);
}
//
inline done() {
this.delay->done();
}
inline reset() {
this.delay->reset();
}
//
inline do() bool {
if func = this.delay->do() {
if !this.done;
this.texture->destroy(), this.done = true;
else
this->fade();
}
}
//
private func fade() {
var alpha uint8 = this.delay->get_per<uint8>(0xff);
var texture void = this.texture->get_texture();
if texture == null {
SDL_SetRenderDrawBlendMode(this.render, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(this.render, this.r, this.g, this.b, alpha);
SDL_RenderFillRect(this.render, &this.rect);
SDL_SetRenderDrawBlendMode(this.render, SDL_BLENDMODE_NONE);
else
this.texture->set_alpha_mod(alpha);
this.texture->draw(this.render,
this.rect.w - (this.rect.w + this.texture->get_width()) / 2,
this.rect.h - (this.rect.h + this.texture->get_height()) / 2);
}
}
}

View File

@@ -1,58 +0,0 @@
class game+, focus_map {
private import rt::c, lib::sdl2;
private alias vector = std::vector;
struct map {
control. control;
up. control;
down. control;
left. control;
right. control;
}
struct focus_map {
map vector<map>;
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
func register(control. control, up. control, down. control, left. control, right. control) {
var map. map = this.map->new();
map.control = control;
map.up = up;
map.down = down;
map.left = left;
map.right = right;
}
func get(control. control, scancode SDL_Scancode) .control {
var count size_t = this.map->count();
while count {
var map. map = this.map->at(--count);
if map.control == control {
if scancode == CPI_SCANCODE_UP {
return map.up;
elseif scancode == CPI_SCANCODE_DOWN;
return map.down;
elseif scancode == CPI_SCANCODE_LEFT;
return map.left;
elseif scancode == CPI_SCANCODE_RIGHT;
return map.right;
else
return null;
}
}
}
return null;
}
}

View File

@@ -1,98 +0,0 @@
class game+, font {
private import rt::c, lib::sdl2_ttf;
struct font {
obj void;
tex texture;
}
func constructor() {
this.obj = null;
constructor(this);
}
func destructor() {
this->close();
destructor(this);
}
func open(font_name. char, size int) bool {
this->close();
if (this.obj = TTF_OpenFont(font_name, size)) == null {
printf("TTF_OpenFont: %s\n", font_name);
return false;
}
return true;
}
func close() {
this.tex->destroy();
if this.obj ~= null;
TTF_CloseFont(this.obj), this.obj = null;
}
// xxx
inline get_width() int {
return this.tex->get_width();
}
inline get_height() int {
return TTF_FontHeight(this.obj);
}
inline get_line_skip() int {
return TTF_FontLineSkip(this.obj);
}
inline get_size(text. char, width. int, height. int) bool {
return TTF_SizeUTF8(this.obj, text, width, height) == 0;
}
func create_tex(render void, text. char, color uint32) void {
var surface void = TTF_RenderUTF8_Solid(this.obj, text, color);
if surface == null;
return null;
func = SDL_CreateTextureFromSurface(render, surface);
SDL_FreeSurface(surface);
}
// fixme
func create_outlined_tex(render void, text. char, text_color uint32, outline_color uint32, outline_size int) void {
TTF_SetFontOutline(this.obj, outline_size);
var outline_texture. SDL_Surface = TTF_RenderUTF8_Solid(this.obj, text, outline_color);
TTF_SetFontOutline(this.obj, 0);
if outline_texture == null;
return null;
var text_texture. SDL_Surface = TTF_RenderUTF8_Solid(this.obj, text, text_color);
if text_texture == null {
SDL_FreeSurface(outline_texture);
return null;
}
SDL_SetSurfaceBlendMode(outline_texture, SDL_BLENDMODE_BLEND);
var rect SDL_Rect;
rect.x = outline_size;
rect.y = outline_size;
rect.w = text_texture.w;
rect.h = text_texture.h;
SDL_BlitSurface(text_texture, null, outline_texture, &rect);
func = SDL_CreateTextureFromSurface(render, outline_texture);
SDL_FreeSurface(outline_texture);
SDL_FreeSurface(text_texture);
}
inline prepare(render void, text. char, color uint32) bool {
return this.tex->init(this->create_tex(render, text, color));
}
inline draw(render void, x int, y int) {
this.tex->draw(render, x, y);
}
inline draw2(render void, x int, y int, text. char, color uint32) {
if this->prepare(render, text, color);
this->draw(render, x, y);
}
}

View File

@@ -1,24 +0,0 @@
class game+, norepeat {
struct norepeat {
lock bool;
}
func constructor() {
this.lock = true;
}
inline do() bool {
if !this.lock {
this.lock = true;
return true;
}
return false;
}
inline set(lock bool = false) {
this.lock = lock;
}
}

View File

@@ -1,39 +0,0 @@
class game+, repeat {
private import lib::sdl2;
struct repeat {
delay delay;
duration int;
inc int;
count int;
remains int;
}
func init(duration uint32, inc int, count int) {
this.delay->init(duration, true);
this.duration = duration;
this.inc = inc;
this.count = count;
this.remains = count;
}
inline reset(done bool = true) {
this.delay->init(this.duration, done);
this.remains = this.count;
}
inline do() bool {
return this.delay->do();
}
func undo() {
if this.remains > 0 {
this.remains--;
this.delay->inc_duration(this.inc);
}
this.delay->undo();
}
}

View File

@@ -1,206 +0,0 @@
class game+, scene+ {
private import rt::c;
private alias vector = std::vector;
struct scene {
struct callback {
update void;
draw void;
wake void;
destructor void;
}
parent. window;
name. char;
controls vector<void>;
focus_control. control;
popup. control;
closing_popup. control;
pending_popup. control;
}
func constructor() {
memset(this, 0, sizeof(scene));
constructor(this);
}
func destructor() {
if this.popup ~= null;
free_control(this.popup);
if this.closing_popup ~= null;
free_control(this.closing_popup);
if this.pending_popup ~= null;
free_control(this.pending_popup);
forvar count size_t = this.controls->count(); count;;
free_control(.this.controls->at(--count));
destructor(this);
}
//
inline set_window(wnd. window) {
this.parent = wnd;
}
inline get_window() .window {
return this.parent;
}
inline set_name(name. char) {
this.name = name;
}
inline get_name() .char {
return this.name;
}
//
inline quit() bool {
return this.parent->pop_scene() ~= null;
}
// control
func new_control<T>(x int, y int, width int = 0, height int = 0, standalone bool = false) .T {
func = malloc_t<T>();
#if objectid(T).func.update;
func.super.callback.update = T::update*;
#endif
#if objectid(T).func.draw;
func.super.callback.draw = T::draw*;
#endif
#if objectid(T).func.wake;
func.super.callback.wake = T::wake*;
#endif
#if objectid(T).func.destructor;
func.super.callback.destructor = T::destructor*;
#endif
func->set_parent(this);
func->set_pos(x, y);
func->set_size(width, height);
#if objectid(T).func.init;
if !func->init(this.parent->get_render()) {
printf("Failed to load \"%s\" control.\n", objectid(T).name);
exit(1);
}
#endif
if !standalone;
this.controls->push_back(func);
}
inline create_control<T>(x int, y int, width int = 0, height int = 0) .T {
return this->new_control<T>(x, y, width, height, true);
}
static func free_control(control. control) {
if control.callback.destructor ~= null {
proto fn(this void);
fn[control.callback.destructor](control);
}
free(control);
}
// focus
func set_focus(control. control) {
var prev. control = this.focus_control;
if prev ~= null;
prev.focus = false;
this.focus_control = control, control.focus = true;
}
inline get_focus() .control {
return this.focus_control;
}
// popup
func close_popup() {
if this.popup ~= null {
this.closing_popup = this.popup;
this.popup = null;
// xxx
if this.callback.wake ~= null {
proto fn(this void);
fn[this.callback.wake](this);
}
}
}
func set_popup(control. control) {
if this.popup == null and this.closing_popup == null {
this.popup = control;
else
if this.pending_popup ~= null;
free_control(this.pending_popup);
this.pending_popup = control;
}
}
func has_popup() bool {
if this.popup ~= null or
this.closing_popup ~= null or
this.pending_popup ~= null {
return true;
}
return false;
}
//
func update(render void) {
proto fn(this void, render void);
if this.closing_popup ~= null;
free_control(this.closing_popup), this.closing_popup = null;
if this.pending_popup ~= null {
if this.popup ~= null;
free_control(this.popup);
this.popup = this.pending_popup;
this.pending_popup = null;
}
// xxx
if this.popup == null {
forvar count size_t = this.controls->count(); count; {
var control. control = .this.controls->at(--count);
if control.callback.update ~= null;
fn[control.callback.update](control, render);
}
else
var popup. control = this.popup;
if popup.callback.update ~= null;
fn[popup.callback.update](popup, render);
}
}
func draw(render void) {
proto fn(this void, render void);
forvar count size_t = this.controls->count(); count; {
var control. control = .this.controls->at(--count);
if control.callback.draw ~= null;
fn[control.callback.draw](control, render);
}
if this.popup ~= null {
var popup. control = this.popup;
if popup.callback.draw ~= null;
fn[popup.callback.draw](popup, render);
}
}
func wake() {
proto fn(this void);
forvar count size_t = this.controls->count(); count; {
var control. control = .this.controls->at(--count);
if control.callback.wake ~= null;
fn[control.callback.wake](control);
}
if this.popup ~= null {
var popup. control = this.popup;
if popup.callback.wake ~= null;
fn[popup.callback.wake](popup);
}
}
}

View File

@@ -1,79 +0,0 @@
class game+, small_font {
private import rt::c, lib::sdl2;
struct small_font {
textures(13) texture;
font_width int;
font_height int;
}
func constructor() {
constructor(this);
this.font_width = 0;
this.font_height = 0;
}
func destructor() {
destructor(this);
}
func init(render void, font_width int, font_height int, filename. char) bool {
var tex texture;
if !tex->load_file(render, filename);
return false;
if tex->get_width() ~= (font_width * 13) or tex->get_height() ~= font_height;
return false;
forvar i int = 0; i < 13; i++;
this.textures[i]->init(tex->clone_tex(render, i * font_width, 0, font_width, font_height, SDL_BLENDMODE_BLEND));
this.font_width = font_width;
this.font_height = font_height;
return true;
}
func draw_cap(render void, x int, y int, cap uint) {
var str(8) char;
forvar index int = 0, count int = snprintf(&str, 8, "%u", cap); index < count; index++ {
this.textures[str[index] - '0']->draw(render, x, y);
x += this.font_width;
}
this.textures[10]->draw(render, x, y);
}
func draw_time(render void, x int, y int, t time_t, draw_colon bool = true) {
var tm. struct_tm = localtime(&t);
if !tm.tm_hour {
tm.tm_hour = 12;
elseif tm.tm_hour > 12;
tm.tm_hour -= 12;
}
var str(8) char;
forvar index int = 0, count int =
sprintf(&str, "%u:%02u",
tm.tm_hour,
tm.tm_min); index < count; index++ {
var c char = str[index];
if isdigit(c) {
this.textures[c - '0']->draw(render, x, y);
elseif draw_colon;
this.textures[11]->draw(render, x, y);
}
x += this.font_width;
}
}
func draw_page(render void, x int, y int, cur uint, last uint) {
var str(16) char;
forvar index int = 0, count int = snprintf(&str, 16, "%u/%u", cur, last); index < count; index++ {
var c char = str[index];
if isdigit(c) {
this.textures[c - '0']->draw(render, x, y);
else
this.textures[12]->draw(render, x, y);
}
x += this.font_width;
}
}
}

View File

@@ -1,151 +0,0 @@
class game+, texture {
private import
rt::c,
lib::sdl2,
lib::sdl2_image;
struct texture {
obj void;
format uint32;
width int;
height int;
auto_destroy bool;
}
func constructor() {
memset(this, 0, sizeof(texture));
this.auto_destroy = true;
}
func destructor() {
this->destroy();
}
func destroy() {
if this.auto_destroy {
if this.obj ~= null;
SDL_DestroyTexture(this.obj);
}
this.obj = null;
this.width = 0;
this.height = 0;
}
func init(texture void, auto_destroy bool = true) bool {
this->destroy();
if texture == null {
return false;
}
if SDL_QueryTexture(texture, &this.format, null, &this.width, &this.height);
return false;
this.obj = texture;
this.auto_destroy = auto_destroy;
return true;
}
func load_file(render void, filename. char) bool {
this->destroy();
if (this.obj = IMG_LoadTexture(render, filename)) == null {
printf("IMG_LoadTexture: %s\n", SDL_GetError());
return false;
}
if SDL_QueryTexture(this.obj, &this.format, null, &this.width, &this.height) {
this->destroy();
return false;
}
this.auto_destroy = true;
return true;
}
func load_file_with_colorkey(render void, filename. char, r uint8, g uint8, b uint8) bool {
var surface. SDL_Surface = IMG_Load(filename);
if surface == null {
printf("IMG_Load: %s\n", SDL_GetError());
return false;
}
if SDL_SetColorKey(surface, SDL_RLEACCEL, SDL_MapRGB(surface.format, r, g, b)) {
SDL_FreeSurface(surface);
return false;
}
var texture void = SDL_CreateTextureFromSurface(render, surface);
SDL_FreeSurface(surface);
if texture == null;
return false;
return this->init(texture);
}
func clone_tex(render void, x int, y int, width int, height int, blend_mode SDL_BlendMode = SDL_BLENDMODE_NONE) void {
if this.obj == null;
return null;
if (func = SDL_CreateTexture(render, this.format, SDL_TEXTUREACCESS_TARGET, width, height)) == null;
return;
SDL_SetRenderTarget(render, func);
SDL_SetTextureBlendMode(func, blend_mode);
SDL_RenderCopy(render, this.obj,
&global::make_rect(x, y, width, height),
&global::make_rect(0, 0, width, height));
SDL_SetRenderTarget(render, null);
}
//
inline draw(render void, x int, y int) {
SDL_RenderCopy(render, this.obj, null,
&this->make_rect(x, y));
}
inline draw2(render void, x int, y int, width int, height int) {
SDL_RenderCopy(render, this.obj,
&global::make_rect(0, 0, width, height),
&global::make_rect(x, y, width, height));
}
inline draw3(render void, x int, y int, width int, height int) {
SDL_RenderCopy(render, this.obj, &this->make_rect(0, 0),
&global::make_rect(x, y, width, height));
}
//
inline make_rect(x int, y int) SDL_Rect {
func.x = x,
func.y = y,
func.w = this.width,
func.h = this.height;
}
//
inline get_texture() void {
return this.obj;
}
inline get_width() int {
return this.width;
}
inline get_height() int {
return this.height;
}
inline get_blend_mode() SDL_BlendMode {
if SDL_GetTextureBlendMode(this.obj, &func);
func = SDL_BLENDMODE_INVALID;
}
inline set_blend_mode(mode SDL_BlendMode) int {
return SDL_SetTextureBlendMode(this.obj, mode);
}
inline get_alpha_mod() uint8 {
if SDL_GetTextureAlphaMod(this.obj, &func);
func = 0;
}
inline set_alpha_mod(alpha uint8) int {
return SDL_SetTextureAlphaMod(this.obj, alpha);
}
}

View File

@@ -1,312 +0,0 @@
class game+, window {
private import rt::c, lib::sdl2, lib::sdl2_image;
private alias
string = std::string,
vector_ptr = std::vector_ptr;
struct window {
wnd void;
render void;
scenes vector_ptr<scene>;
garbage vector_ptr<scene>;
current_scene. scene;
pending_scene. scene;
turbo uint32;
quit bool;
}
func constructor() {
memset(this, 0, sizeof(window));
constructor(this);
}
func destructor() {
if this.current_scene ~= null;
this->safe_free_scene(this.current_scene);
if this.pending_scene ~= null;
this->safe_free_scene(this.pending_scene);
using count size_t = this.scenes->count() {
while count {
this->free_scene_internal(this.scenes->at(--count));
}
}
this->dump();
if this.render ~= null;
SDL_DestroyRenderer(this.render);
if this.wnd ~= null;
SDL_DestroyWindow(this.wnd);
destructor(this);
}
func create_wnd(title. char, w int, h int,
x int = SDL_WINDOWPOS_UNDEFINED,
y int = SDL_WINDOWPOS_UNDEFINED) bool {
if (this.wnd = SDL_CreateWindow(title, x, y, w, h,
SDL_WINDOW_FULLSCREEN |
SDL_WINDOW_OPENGL |
SDL_WINDOW_SHOWN)) == null;
return false;
if (this.render = SDL_CreateRenderer(this.wnd, -1,
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_TARGETTEXTURE)) == null {
SDL_DestroyWindow(this.wnd), this.wnd = null;
return false;
}
return true;
}
// scene
func new_scene<T>() .T {
func = malloc_t<T>();
#if objectid(T).func.update;
func.super.callback.update = T::update*;
#endif
#if objectid(T).func.draw;
func.super.callback.draw = T::draw*;
#endif
#if objectid(T).func.wake;
func.super.callback.wake = T::wake*;
#endif
#if objectid(T).func.destructor;
func.super.callback.destructor = T::destructor*;
#endif
func->set_window(this);
func->set_name(objectid(T).name);
#if objectid(T).func.init;
if !func->init(this.render) {
printf("Failed to load \"%s\" scene.\n", objectid(T).name);
exit(1);
}
#endif
}
private static func free_scene_internal(scene. scene) {
if scene.callback.destructor ~= null {
proto fn(this void);
fn[scene.callback.destructor](scene);
}
free(scene);
}
inline free_scene(scene. scene) {
this.garbage->push_back(scene);
}
func safe_free_scene(scene. scene) {
var count size_t = this.scenes->count();
while count {
if this.scenes->at(--count) == scene {
return;
}
}
this->free_scene(scene);
}
inline push_scene(scene. scene) {
this.scenes->push_back(scene);
}
inline get_last_scene() .scene {
if this.scenes->empty();
return null;
return this.scenes->back();
}
inline pop_scene() .scene {
if this.scenes->empty();
return null;
this->set_scene(func = this.scenes->back());
this.scenes->pop_back();
if func.callback.wake ~= null {
proto fn(this void);
fn[func.callback.wake](func);
}
}
func set_scene(scene. scene) {
if this.current_scene == null {
this.current_scene = scene;
else
if this.pending_scene ~= null;
this->safe_free_scene(this.pending_scene);
this.pending_scene = scene;
}
}
inline set_new_scene<T>() {
this->set_scene(this->new_scene<T>());
}
private inline swap_scene() {
if this.pending_scene ~= null {
if this.current_scene ~= null;
this->safe_free_scene(this.current_scene);
this.current_scene = this.pending_scene;
this.pending_scene = null;
}
}
//
inline dump() {
var count size_t = this.garbage->count();
while count {
this->free_scene_internal(this.garbage->at(--count));
}
this.garbage->clear();
}
//
inline update() {
var scene. scene = this.current_scene;
if scene.callback.update ~= null {
proto fn(this void, render void);
fn[scene.callback.update](scene, this.render);
}
}
inline draw() {
var scene. scene = this.current_scene;
if scene.callback.draw ~= null {
proto fn(this void, render void);
fn[scene.callback.draw](scene, this.render);
}
}
inline present() {
SDL_RenderPresent(this.render);
}
//
inline enable_turbo(ms int) {
this.turbo = SDL_GetTicks() + ms;
}
//
inline quit() {
this.quit = true;
}
//
func on_keydown(event. SDL_KeyboardEvent) {
if !event.repeat {
if event.keysym.scancode == CPI_SCANCODE_SHIFT_START {
var surface void = this->screen_capture_to_surface2();
if surface ~= null {
var tm. struct_tm = localtime(&time(null));
var filename string;
IMG_SavePNG(surface, filename->format("screenshots/%04d-%02d-%02d-%02d_%02d_%02d_%04d.png",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, random<int>(10000)));
SDL_FreeSurface(surface);
}
}
}
}
//
func game_loop() {
this->enable_turbo(8000);
while !this.quit {
var event SDL_Event;
while SDL_PollEvent(&event) {
if event.type == SDL_KEYDOWN {
this->on_keydown(&event.key);
this->enable_turbo(3000);
elseif event.type == SDL_QUIT;
return;
}
}
this->update();
if this.pending_scene == null {
this->draw();
this->present();
}
this->swap_scene();
this->dump();
if this.turbo < SDL_GetTicks() {
forvar standby uint32 = SDL_GetTicks() + 300 ;; {
if SDL_PollEvent(&event) {
if event.type == SDL_KEYDOWN {
this->on_keydown(&event.key);
this->enable_turbo(3000);
break;
elseif event.type == SDL_QUIT;
return;
}
}
if SDL_GetTicks() > standby;
break;
usleep(50000);
}
else
usleep(3000);
}
}
}
//
inline get_handle() void {
return this.wnd;
}
inline get_render() void {
return this.render;
}
inline get_scene() .scene {
return this.scene;
}
inline get_size(w. int, h. int) {
SDL_GetWindowSize(this.wnd, w, h);
}
//
func screen_capture_to_surface(rect. SDL_Rect) void {
var format uint32 = SDL_GetWindowPixelFormat(this.wnd);
var surface. SDL_Surface = SDL_CreateRGBSurfaceWithFormat(0, rect.w, rect.h, 24, format);
if surface == null;
return null;
if SDL_LockSurface(surface) {
SDL_FreeSurface(surface);
return null;
}
SDL_RenderReadPixels(this.render, rect, format, surface.pixels, surface.pitch);
SDL_UnlockSurface(surface);
return surface;
}
func screen_capture_to_surface2() void {
var rect SDL_Rect = 0;
this->get_size(&rect.w, &rect.h);
return this->screen_capture_to_surface(&rect);
}
func screen_capture(rect. SDL_Rect) void {
var surface void = this->screen_capture_to_surface(rect);
if surface == null;
return null;
func = SDL_CreateTextureFromSurface(this.render, surface);
SDL_FreeSurface(surface);
}
func screen_capture2() void {
var surface void = this->screen_capture_to_surface2();
if surface == null;
return null;
func = SDL_CreateTextureFromSurface(this.render, surface);
SDL_FreeSurface(surface);
}
}

View File

@@ -1,120 +0,0 @@
module game+, global {
private import rt::c, lib::sdl2;
private alias
string = std::string,
strings = std::strings;
var config cfg;
var skin_dir string;
var apps app_list;
var wifi wifi;
// deprecated
var outlined_font bool = false;
var uni_font font;
var small_font small_font;
//
func init(render void) bool {
if !config->open("bean.cfg");
return false;
if config->find("skin") == null;
config->add("skin", "default");
if config->find("font") == null;
config->add("font", "unifont-12.0.01.ttf");
// deprecated
using value. char = config->get("outlined_font") {
if value ~= null and !strcasecmp(value, "true") {
outlined_font = true;
}
}
skin_dir->format("skins/%s",
config->get("skin"));
if !apps->init("bean.db");
return false;
if !wifi->init();
return false;
var filename string;
if !uni_font->open(filename->format("fonts/%s", config->get("font")), 16);
return false;
small_font->init(render, 10, 12,
make_path("small_font_10x12.png"));
return true;
}
//
func make_path(filename. char) .char {
static path string;
return path->format("%s/%s",
skin_dir->ptr(), filename);
}
inline make_rect(x int, y int, width int, height int) SDL_Rect {
func.x = x,
func.y = y,
func.w = width,
func.h = height;
}
//
func get_backlight_level() byte {
func = -1;
var stream void = fopen(CPI_BACKLIGHT, "r");
if stream ~= null {
if fread(&func, 1, 1, stream) == 1;
func -= '0';
fclose(stream);
}
}
func set_backlight_level(level byte) bool {
var stream void = fopen(CPI_BACKLIGHT, "w");
if stream ~= null {
defer fclose(stream);
level += '0';
if fwrite(&level, 1, 1, stream) == 1;
return true;
}
return false;
}
func get_battery_cap() int {
var lines strings;
if lines->load_file(CPI_BATTERY) <= 0;
return -1;
var strs strings;
func = 0;
forvar index size_t = 0, count size_t = lines->count(); index < count; index++ {
var line. char = lines->item(index);
if strstr(line, "POWER_SUPPLY_STATUS=") ~= null {
if strs->split(line, "=") == 2 {
if !strcasecmp(strs->item(1), "Charging");
func = 0x100;
}
break;
}
}
forvar index size_t = 0, count size_t = lines->count(); index < count; index++ {
var line. char = lines->item(index);
if strstr(line, "POWER_SUPPLY_CAPACITY=") ~= null {
strs->clear();
if strs->split(line, "=") == 2;
return func | atoi(strs->item(1));
break;
}
}
return -1;
}
}

View File

@@ -1,25 +0,0 @@
class game+, launcher {
private import lib::sdl2;
struct launcher {
wnd window;
}
func constructor() {
constructor(this); }
func destructor() {
destructor(this); }
func start(title. char) bool {
if !this.wnd->create_wnd(title, CPI_WIDTH, CPI_HEIGHT);
return false;
if !global::init(this.wnd->get_render());
return false;
this.wnd->set_new_scene<scene::intro>();
this.wnd->game_loop();
return true;
}
}

View File

@@ -1,699 +0,0 @@
/*
set_callback(on_select void, on_close void, arg void)
set_fadeout(fadeout. fadeio)
set_ext(ext. char)
set_dir(render void, dir_name. char) bool
refresh(render void) bool
set_mode(mode mode)
set_exec_format(format. char)
hidden_files(visible bool)
cursor_to(name. char) bool
goto_parent_dir(render void) bool
get_dir_count() size_t
get_file_count() size_t
get_all_count() size_t
get_path() .char
close()
*/
class game+, scene+, file_browser {
inherit game::scene = super;
private import rt::c, lib::sdl2;
private alias
string = std::string,
strings = std::strings,
vector = std::vector;
private alias popup_menu = control::popup_menu;
enum mode {
browse,
select,
select_file,
select_dir,
select_image,
exec
}
struct file {
icon texture;
black_font texture;
white_font texture;
link bool;
type uchar;
str(NAME_MAX) char;
}
struct file_browser {
struct tex {
dir texture;
reg texture;
lnk texture;
name texture;
image texture;
empty texture;
}
fadeio fadeio;
fadeout. fadeio;
image_timer delay;
input_delay repeat;
input_lock norepeat;
root string;
path string;
ext strings;
dirs vector<file>;
files vector<file>;
on_select void;
on_close void;
arg void;
cursor int;
start_index int;
exec_format string;
mode mode;
hidden_files bool;
}
func constructor() {
memset(this, 0, sizeof(file_browser));
constructor(this);
}
func destructor() {
destructor(this);
}
define {
TOP_HEIGHT = 23;
ITEM_HEIGHT = 25;
SCROLL_WIDTH = 8;
SCROLL_HEIGHT = 80;
}
func init(render void) bool {
this.tex.dir->load_file(render,
global::make_path("file_browser/dir.png"));
this.tex.reg->load_file(render,
global::make_path("file_browser/reg.png"));
this.tex.lnk->load_file(render,
global::make_path("file_browser/lnk.png"));
this.tex.empty->init(
global::uni_font->create_tex(render, "Empty", 0xff000000));
var wnd. window = this->get_window();
this.fadeio->init(wnd, 300);
this.fadeio->set_texture(wnd->screen_capture2());
this.image_timer->init(300);
this.input_delay->init(300, -48, 6);
this.exec_format->set("%s");
return true;
}
/*
on_select = lambda(filename. char, arg void) [
];
on_close = lambda(arg void) [
];
*/
inline set_callback(on_select void, on_close void, arg void) {
this.on_select = on_select;
this.on_close = on_close;
this.arg = arg;
}
inline set_fadeout(fadeout. fadeio) {
this.fadeout = fadeout;
}
private inline reload_image() {
this.tex.image->destroy();
this.image_timer->reset();
}
/*
slow
*/
private static func sort(items. vector<file>) {
forvar i int = 0, c int = items->count() - 1; i < c; i++ {
forvar j int = 0; j < c - i; j++ {
var x. file = items->at(j);
var y. file = items->at(j + 1);
if strcmp(&x.str, &y.str) > 0 {
var tmp $file = .x;
.x = .y;
.y = tmp;
}
}
}
}
func set_ext(ext. char) {
this.ext->clear();
this.ext->split(ext, ",");
}
private func is_allow_ext(filename. char) bool {
if this.ext->empty();
return true;
var extension. char = strrchr(filename, '.');
if extension == null {
extension = "?";
else
extension++;
}
var count size_t = this.ext->count();
while count {
if !strcasecmp(this.ext->item(--count), extension);
return true;
}
return false;
}
func set_dir(render void, dir_name. char, root bool = false) bool {
var dir void = opendir(dir_name);
if dir == null;
return false;
this.tex.name->init(
global::uni_font->create_tex(render, dir_name, 0xffffffff));
this.path->set(dir_name);
while this.path->len() > 1 and
this.path->ends_with('/');
this.path->remove_back();
if root;
this.root->set(this.path->ptr());
this.dirs->clear();
this.files->clear();
this.cursor = 0;
this.start_index = 0;
using ent. struct_dirent {
while (ent = readdir(dir)) ~= null {
var file. file;
var link bool = false;
if ent.d_type == DT_LNK {
var str string;
var path. char = realpath(str->format("%s/%s", this.path->ptr(), &ent.d_name), null);
if path == null;
continue;
defer free(path);
var st struct_stat;
if stat(path, &st);
continue;
if S_ISDIR(st.st_mode) {
ent.d_type = DT_DIR;
elseif S_ISREG(st.st_mode);
ent.d_type = DT_REG;
else
ent.d_type = DT_UNKNOWN;
}
link = true;
}
if this.hidden_files and ent.d_name[0] == '.' {
continue;
}
if ent.d_type == DT_DIR {
if ent.d_name[0] == '.' and !ent.d_name[1] or
ent.d_name[1] == '.' and !ent.d_name[2] {
file = null;
else
file = this.dirs->new();
file.icon->init(this.tex.dir->get_texture(), false);
}
elseif ent.d_type == DT_REG;
if this->is_allow_ext(&ent.d_name) {
file = this.files->new();
file.icon->init(this.tex.reg->get_texture(), false);
else
file = null;
}
else
file = null;
}
if file ~= null {
file.link = link;
file.type = ent.d_type;
strcpy(&file.str, &ent.d_name);
}
}
}
closedir(dir);
this->sort(&this.dirs);
this->sort(&this.files);
this->reload_image();
return true;
}
inline refresh(render void) bool {
return this->set_dir(render, this.path->ptr());
}
inline set_mode(mode mode) {
this.mode = mode;
}
inline set_exec_format(format. char) {
this.exec_format->set(format);
}
inline hidden_files(visible bool) {
this.hidden_files = visible;
}
func cursor_to(name. char) bool {
forvar index size_t = 0, count size_t = this.dirs->count(); index < count; index++ {
if !strcmp(&this.dirs->at(index).str, name) {
this.cursor = index;
this->update_scroll();
this->reload_image();
return true;
}
}
forvar index size_t = 0, count size_t = this.files->count(); index < count; index++ {
if !strcmp(&this.files->at(index).str, name) {
this.cursor = this.dirs->count() + index;
this->update_scroll();
this->reload_image();
return true;
}
}
return false;
}
func goto_parent_dir(render void) bool {
if this.path->empty();
return false;
var path string;
path->set(this.path->ptr());
while path->ends_with('/');
path->remove_back();
if path->empty();
return true;
/*
fixme
*/
if !strcmp(path->ptr(), this.root->ptr()) {
this->close();
return true;
}
var slash. char = strrchr(path->ptr(), '/');
if slash == null;
return false;
var cur_dir string;
cur_dir->set(slash + 1);
if slash == path->ptr() {
path->set("/");
else
path->set(path->ptr(), slash - path->ptr());
}
if func = this->set_dir(render, path->ptr()) {
if !cur_dir->empty() {
this->cursor_to(cur_dir->ptr());
}
}
}
inline get_dir_count() size_t {
return this.dirs->count();
}
inline get_file_count() size_t {
return this.files->count();
}
inline get_all_count() size_t {
return this.dirs->count() + this.files->count();
}
inline get_path() .char {
return this.path->ptr();
}
private func get_selected_file() .file {
var cursor int = this.cursor;
var dir_count size_t = this.dirs->count();
if dir_count and cursor < dir_count {
return this.dirs->at(cursor);
else
if (cursor -= dir_count) < this.files->count();
return this.files->at(cursor);
return null;
}
}
func close() {
if this.on_close ~= null {
proto fn(arg void);
fn[this.on_close](this.arg);
}
if this.fadeout ~= null {
this.fadeout->set_texture(this->get_window()->screen_capture2());
this.fadeout->reset();
}
this->quit();
}
private func select(filename. char) {
if this.on_select ~= null {
proto fn(filename. char, arg void);
fn[this.on_select](filename, this.arg);
}
this->close();
}
private func exec(filename. char) {
var str string;
exec3(this->get_window(), "Please Wait",
str->format(this.exec_format->ptr(), filename));
}
private func action(render void) {
var file. file = this->get_selected_file();
if file ~= null {
if file.type == DT_DIR {
var new_path string;
new_path->set(this.path->ptr());
while new_path->ends_with('/');
new_path->remove_back();
this->set_dir(render,
new_path->appendf("/%s", &file.str));
elseif file.type == DT_REG;
if this.mode == mode.select or
this.mode == mode.select_file or
this.mode == mode.select_image {
var filename string;
this->select(filename->format("%s/%s",
this->get_path(), &file.str));
elseif this.mode == mode.exec;
var filename string;
this->exec(filename->format("%s/%s",
this->get_path(), &file.str));
}
}
}
}
private func show_popup(render void, file. file) {
// MENU_COPY
// MENU_PASTE
define {
MENU_REFRESH = 1;
MENU_EXECUTE = 2;
MENU_SELECT = 3;
MENU_LINK = 4;
MENU_DELETE = 5;
MENU_EXIT = 6;
}
this->close_popup();
var popup. popup_menu = this->create_control<popup_menu>(0, 0);
popup->set_callback(
lambda(id int, this.file_browser) [
if id == MENU_REFRESH {
this->refresh(this->get_window()->get_render());
elseif id == MENU_EXECUTE;
var file. file = this->get_selected_file();
if file ~= null {
var filename string;
this->exec(filename->format("%s/%s",
this->get_path(), &file.str));
}
elseif id == MENU_SELECT;
var file. file = this->get_selected_file();
if file ~= null {
var filename string;
this->select(filename->format("%s/%s",
this->get_path(), &file.str));
}
elseif id == MENU_LINK;
var file. file = this->get_selected_file();
if file ~= null {
var parent. scene::main = this->get_window()->get_last_scene();
if parent ~= null {
if !strcmp(parent->get_name(), "main") {
import scene::main;
var tile_menu. tile_menu = parent.tile_menu;
tile_menu->set_mode(tile_menu::mode.link);
var filename string;
var link string;
link->format(this.exec_format->ptr(),
filename->format("%s/%s", this->get_path(), &file.str));
tile_menu->set_link(link->ptr());
this->close();
}
}
}
elseif id == MENU_DELETE;
var file. file = this->get_selected_file();
if file ~= null {
var filename string;
system(filename->format("sudo rm -rf \"%s/%s\"",
this->get_path(), &file.str));
// TODO
}
elseif id == MENU_EXIT;
this->close();
}
],
lambda(this.file_browser) [
this->close_popup();
], this);
popup->add_menu(render, MENU_REFRESH, "Refresh");
if file ~= null {
if file.type == DT_REG {
var filename string;
var st struct_stat;
if !stat(filename->format("%s/%s", this->get_path(), &file.str), &st) {
if st.st_mode & S_IXUSR {
popup->add_menu(render, MENU_EXECUTE, "Execute");
}
}
if this.mode == mode.browse or
this.mode == mode.exec {
popup->add_menu(render, MENU_LINK, "Link");
}
elseif file.type == DT_DIR;
if this.mode == mode.select or
this.mode == mode.select_dir {
popup->add_menu(render, MENU_SELECT, "Select");
}
}
}
// popup->add_menu(render, MENU_DELETE, "Delete");
popup->add_menu(render, MENU_EXIT, "Exit");
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
popup->set_pos(
(rect.w - popup->get_width()) / 2,
(rect.h - popup->get_height()) / 2);
this->set_popup(popup);
}
private func update_scroll() {
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
if this.start_index > this.cursor {
this.start_index = this.cursor;
else
var display_count int = (rect.h - TOP_HEIGHT) / ITEM_HEIGHT;
var delta int = this.cursor - this.start_index + 1;
if display_count < delta;
this.start_index += delta - display_count;
}
}
func update(render void) {
if this->has_popup() {
this.super->update(render);
else
if this.image_timer->do() {
if this.mode == mode.select_image {
if this.tex.image->get_texture() == null {
var file. file = this->get_selected_file();
if file ~= null {
if file.type == DT_REG {
var filename string;
this.tex.image->load_file(render,
filename->format("%s/%s", this->get_path(), &file.str));
}
}
this.image_timer->reset();
}
}
}
var state. uint8 = SDL_GetKeyboardState(null);
if state[CPI_SCANCODE_UP] {
if this.input_delay->do() {
if this.cursor {
this.cursor--;
this->update_scroll();
this->reload_image();
}
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_DOWN];
if this.input_delay->do() {
if this.cursor < this->get_all_count() -1 {
this.cursor++;
this->update_scroll();
this->reload_image();
}
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_LEFT];
if this.input_delay->do() {
if this.cursor - 10 < 0 {
this.cursor = 0;
else
this.cursor -= 10;
}
this->update_scroll();
this->reload_image();
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_RIGHT];
if this.input_delay->do() {
if this.cursor + 10 < this->get_all_count() -1 {
this.cursor += 10;
else
this.cursor = this->get_all_count() -1;
}
this->update_scroll();
this->reload_image();
this.input_delay->undo();
}
else
this.input_delay->reset();
}
if state[CPI_SCANCODE_A] {
if this.input_lock->do();
this->goto_parent_dir(render);
elseif state[CPI_SCANCODE_B];
if this.input_lock->do();
this->action(render);
elseif state[CPI_SCANCODE_MENU];
if this.input_lock->do();
this->show_popup(render, this->get_selected_file());
else
this.input_lock->set(false);
}
}
}
private func draw_items(render void, items. vector<file>, begin size_t, cursor int, rect. SDL_Rect, x int, y& int) bool {
forvar index size_t = begin, count size_t = items->count(); index < count; index++ {
var item. file = items->at(index);
var sub_rect SDL_Rect;
sub_rect.x = 0;
sub_rect.y = y;
sub_rect.w = rect.w;
sub_rect.h = ITEM_HEIGHT;
if index + cursor == this.cursor {
SDL_SetRenderDrawColor(render, 0x00, 0xa2, 0xe8, 0xff);
SDL_RenderFillRect(render, &sub_rect);
if item.white_font->get_texture() == null {
item.white_font->init(
global::uni_font->create_tex(render, &item.str, 0xffffffff));
}
item.white_font->draw(render, x + item.icon->get_width() + 3,
y + (ITEM_HEIGHT - item.white_font->get_height()) / 2);
else
if (y - TOP_HEIGHT) / ITEM_HEIGHT % 2 {
SDL_SetRenderDrawColor(render, 0xe0, 0xe0, 0xe0, 0xff);
SDL_RenderFillRect(render, &sub_rect);
}
if item.black_font->get_texture() == null {
item.black_font->init(
global::uni_font->create_tex(render, &item.str, 0xff000000));
}
item.black_font->draw(render, x + item.icon->get_width() + 3,
y + (ITEM_HEIGHT - item.black_font->get_height()) / 2);
}
item.icon->draw(render, x,
y + (ITEM_HEIGHT - item.icon->get_height()) / 2);
if item.link {
this.tex.lnk->draw(render, x,
y + (ITEM_HEIGHT - this.tex.lnk->get_height()) / 2);
}
if (y += ITEM_HEIGHT) > rect.h;
return false;
}
return true;
}
func draw(render void) {
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(render);
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
var sub_rect SDL_Rect;
sub_rect.x = 0;
sub_rect.y = 0;
sub_rect.w = rect.w;
sub_rect.h = TOP_HEIGHT;
SDL_SetRenderDrawColor(render, 0x35, 0x35, 0x35, 0xff);
SDL_RenderFillRect(render, &sub_rect);
if this.tex.name->get_width() > rect.w {
this.tex.name->draw(render,
-(this.tex.name->get_width() - rect.w) - 4,
(TOP_HEIGHT - this.tex.name->get_height()) / 2);
else
this.tex.name->draw(render,
(rect.w - this.tex.name->get_width()) / 2,
(TOP_HEIGHT - this.tex.name->get_height()) / 2);
}
var file_count int = this->get_all_count();
if file_count {
var x int = 4;
var y int = TOP_HEIGHT;
var dir_count size_t = this.dirs->count();
if dir_count and this.start_index < dir_count {
if this->draw_items(render, &this.dirs, this.start_index, 0, &rect, x, y);
this->draw_items(render, &this.files, 0, dir_count, &rect, x, y);
else
this->draw_items(render, &this.files, this.start_index - dir_count, dir_count, &rect, x, y);
}
var display_count int = (rect.h - TOP_HEIGHT) / ITEM_HEIGHT;
if display_count < file_count {
sub_rect.x = rect.w - SCROLL_WIDTH;
sub_rect.y = TOP_HEIGHT +
int((float(this.start_index) / (file_count - display_count)) *
(rect.h - (TOP_HEIGHT + SCROLL_HEIGHT)));
sub_rect.w = SCROLL_WIDTH;
sub_rect.h = SCROLL_HEIGHT;
SDL_SetRenderDrawColor(render, 0x80, 0x80, 0x80, 0xff);
SDL_RenderFillRect(render, &sub_rect);
}
else
this.tex.empty->draw(render,
(rect.w - this.tex.empty->get_width()) / 2,
(rect.h - this.tex.empty->get_height()) / 2);
}
define {
IMAGE_MAX_WIDTH = 80;
IMAGE_MAX_HEIGHT = 80;
IMAGE_GAP = 15;
}
if this.tex.image->get_texture() ~= null {
var width int = this.tex.image->get_width();
var height int = this.tex.image->get_height();
if width > IMAGE_MAX_WIDTH;
width = IMAGE_MAX_WIDTH;
if height > IMAGE_MAX_HEIGHT;
height = IMAGE_MAX_HEIGHT;
this.tex.image->draw3(render,
rect.w - (width + IMAGE_GAP),
rect.h - (height + IMAGE_GAP), width, height);
}
this.super->draw(render);
this.fadeio->do();
}
func wake() {
this.input_delay->reset(false);
this.input_lock->set(true);
this.super->wake();
}
}

View File

@@ -1,42 +0,0 @@
class game+, scene+, intro {
inherit game::scene = super;
private import lib::sdl2;
struct intro {
fadeio fadeio;
delay delay;
logo texture;
}
func constructor() {
constructor(this); }
func destructor() {
destructor(this); }
func init(render void) bool {
this.fadeio->init(this->get_window(), 2000);
this.fadeio->set_color(235, 235, 235);
this.delay->init(1000);
this.logo->load_file(render,
global::make_path("logo.png"));
return true;
}
func draw(render void) {
SDL_SetRenderDrawColor(render, 235, 235, 235, 0xff);
SDL_RenderClear(render);
var wnd. window = this->get_window();
var rect SDL_Rect = 0;
wnd->get_size(&rect.w, &rect.h);
this.logo->draw(render,
rect.w - (rect.w + this.logo->get_width()) / 2,
rect.h - (rect.h + this.logo->get_height()) / 2);
if this.fadeio->do() and this.delay->do() {
wnd->set_new_scene<scene::main>();
}
}
}

View File

@@ -1,646 +0,0 @@
/*
set_callback(on_done void, on_close void, arg void)
set_fadeout(fadeout. fadeio)
set_title(render void, title. char)
set_text(render void, text. char)
get_text() .char
close()
*/
class game+, scene+, keybd {
inherit game::scene = super;
private import rt::c, std::utf8, lib::sdl2;
private alias string = std::string;
private define {
BUTTON_COL = 11;
BUTTON_ROW = 4;
BUTTON_COUNT = BUTTON_COL * BUTTON_ROW;
BUTTON_WIDTH = 25;
BUTTON_HEIGHT = 23;
BUTTON_GAP = 3;
}
private var layout(3, BUTTON_COUNT) char = {
// 0
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '_',
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ':', '\'',
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '=',
// 1
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '+',
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '\\',
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '"',
'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '|',
// 2
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
'~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '_',
'(', ')', '[', ']', '{', '}', ':', ';', '\'', '"', '\\',
',', '.', '/', '=', '<', '>', '?', '|', '+', '\0', '\0'
};
private define {
SHIFT = -1;
BACKSPACE = -2;
SPACE = -3;
TAB = -4;
RETURN = -5;
}
struct keybd {
struct tex {
title texture;
text texture;
}
fadeio fadeio;
fadeout. fadeio;
caret_timer delay;
cursor_delay repeat;
remove_delay repeat;
input_lock norepeat;
buf string;
on_done void;
on_close void;
arg void;
mode int;
lock bool;
prev_mode int;
prev_lock bool;
cursor int;
prev_cursor int;
start_x int;
caret_pos int;
caret_x int;
draw_caret bool;
enable_return bool;
enable_shift bool;
}
func constructor() {
memset(this, 0, sizeof(keybd));
constructor(this);
}
func destructor() {
destructor(this);
}
module singleton {
var initd bool = false;
var ascii(128) texture;
var shift texture;
var shift_white texture;
var backspace texture;
var space texture;
var tab texture;
var ret texture;
}
func init(render void) bool {
if !singleton::initd {
var str(2) char = 0;
forvar c int = 1; c < 128; c++ {
str[0] = c;
singleton::ascii[c]->init(
global::uni_font->create_tex(render, &str, 0xff000000));
}
singleton::shift->init(
global::uni_font->create_tex(render, "Shift", 0xff000000));
singleton::shift_white->init(
global::uni_font->create_tex(render, "Shift", 0xffffffff));
singleton::backspace->init(
global::uni_font->create_tex(render, "Back", 0xff000000));
singleton::space->init(
global::uni_font->create_tex(render, "Space", 0xff000000));
singleton::tab->init(
global::uni_font->create_tex(render, "Tab", 0xff000000));
singleton::ret->init(
global::uni_font->create_tex(render, "Return", 0xff000000));
singleton::initd = true;
}
var wnd. window = this->get_window();
this.fadeio->init(wnd, 300);
this.fadeio->set_texture(wnd->screen_capture2());
this.caret_timer->init(450);
this.cursor_delay->init(300, -65, 4);
this.remove_delay->init(300, -42, 7);
this.prev_cursor = -1;
this.draw_caret = true;
this.enable_shift = true;
return true;
}
/*
on_done = lambda(text. char, arg void) [
];
on_close = lambda(arg void) [
];
*/
inline set_callback(on_done void, on_close void, arg void) {
this.on_done = on_done;
this.on_close = on_close;
this.arg = arg;
}
inline set_fadeout(fadeout. fadeio) {
this.fadeout = fadeout;
}
func set_title(render void, title. char) {
this.tex.title->init(
global::uni_font->create_tex(render, title, 0xff000000));
}
private inline update_text(render void) {
this.tex.text->init(
global::uni_font->create_tex(render, this.buf->ptr(), 0xff000000));
}
private define {
TEXT_GAP = 10;
}
private func set_caret(pos int) {
this.caret_timer->reset();
this.caret_pos = pos;
var nul. char = this.buf->ptr(this.caret_pos);
var tmp char = .nul;
.nul = 0;
var caret_x int;
if global::uni_font->get_size(this.buf->ptr(), &caret_x, null) {
if this.caret_x = caret_x {
this.caret_x++;
else
this.caret_x--;
}
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
if this.tex.text->get_width() > (rect.w -= TEXT_GAP) {
if this.caret_x < this.start_x {
this.start_x = this.caret_x;
else
if (this.caret_x - this.start_x) > rect.w;
this.start_x = this.caret_x - rect.w;
}
else
this.start_x = 0;
}
else
this.start_x = 0;
this.caret_x = 0;
}
.nul = tmp;
this.draw_caret = true;
}
func set_text(render void, text. char) {
this.buf->set(text);
this->update_text(render);
this.start_x = 0;
this->set_caret(this.buf->len());
}
inline get_text() .char {
return this.buf->ptr();
}
private func insert_char(render void, c char) {
var buf(2) char;
buf[0] = c;
buf[1] = 0;
this.buf->insert(this.caret_pos, &buf);
this->update_text(render);
this->set_caret(this.caret_pos + 1);
}
private func insert(render void, str. char) {
this.buf->insert(this.caret_pos, str);
this->update_text(render);
this->set_caret(this.caret_pos + strlen(str));
}
private func remove(render void) bool {
var tail int;
var len int = utf8len_s(this.buf->ptr(), this.caret_pos, &tail);
if len == -1;
return false;
if tail {
if this.buf->remove(this.caret_pos - tail, tail) {
this->update_text(render);
this->set_caret(this.caret_pos - tail);
}
}
return true;
}
private func toggle_shift() {
if this.mode == 0 {
this.mode = 1;
elseif this.mode == 1;
if this.lock {
this.mode = 0;
this.lock = false;
else
this.lock = true;
}
}
}
private func move_caret(left_right bool) bool {
if left_right {
var tail int;
var len int = utf8len_s(this.buf->ptr(), this.caret_pos, &tail);
if len == -1;
return false;
if tail {
this->set_caret(this.caret_pos - tail);
}
else
if this.caret_pos >= this.buf->len();
return false;
var size int = utf8table[uchar(.this.buf->ptr(this.caret_pos))];
if (this.caret_pos + size) > this.buf->len();
return false;
this->set_caret(this.caret_pos + size);
}
return true;
}
func close() {
if this.on_close ~= null {
proto fn(arg void);
fn[this.on_close](this.arg);
}
if this.fadeout ~= null {
this.fadeout->set_texture(this->get_window()->screen_capture2());
this.fadeout->reset();
}
this->quit();
}
private func done() {
if this.on_done ~= null {
proto fn(text. char, arg void);
fn[this.on_done](this.buf->ptr(), this.arg);
}
this->close();
}
func update(render void) {
if this.caret_timer->do() {
this.draw_caret = !this.draw_caret;
this.caret_timer->undo();
}
var state. uint8 = SDL_GetKeyboardState(null);
if state[CPI_SCANCODE_LEFT] {
if this.cursor_delay->do() {
if this.cursor < 0 {
this.prev_cursor = -1;
if this.cursor == SHIFT {
this.cursor = TAB;
elseif this.cursor == SPACE;
this.cursor = SHIFT;
elseif this.cursor == RETURN;
this.cursor = SPACE;
elseif this.cursor == BACKSPACE;
if this.enable_return {
this.cursor = RETURN;
else
this.cursor = SPACE;
}
else
this.cursor = BACKSPACE;
}
else
if this.cursor % BUTTON_COL {
this.cursor--;
else
this.cursor = (this.cursor / BUTTON_COL + 1) * BUTTON_COL - 1;
}
}
this.cursor_delay->undo();
}
elseif state[CPI_SCANCODE_RIGHT];
if this.cursor_delay->do() {
if this.cursor < 0 {
this.prev_cursor = -1;
if this.cursor == TAB {
this.cursor = SHIFT;
elseif this.cursor == SHIFT;
this.cursor = SPACE;
elseif this.cursor == SPACE;
if this.enable_return {
this.cursor = RETURN;
else
this.cursor = BACKSPACE;
}
elseif this.cursor == RETURN;
this.cursor = BACKSPACE;
else
this.cursor = TAB;
}
else
if this.cursor % BUTTON_COL == BUTTON_COL - 1 {
this.cursor = (this.cursor / BUTTON_COL) * BUTTON_COL;
else
this.cursor++;
}
}
this.cursor_delay->undo();
}
elseif state[CPI_SCANCODE_UP];
if this.cursor_delay->do() {
if this.cursor < 0 {
if this.prev_cursor < 0 {
if this.cursor == TAB {
this.cursor = BUTTON_COUNT - BUTTON_COL;
elseif this.cursor == SHIFT;
this.cursor = BUTTON_COUNT - (BUTTON_COL - 2);
elseif this.cursor == SPACE;
this.cursor = BUTTON_COUNT - (BUTTON_COL - 4);
elseif this.cursor == RETURN;
this.cursor = BUTTON_COUNT - (BUTTON_COL - 7);
else
this.cursor = BUTTON_COUNT - (BUTTON_COL - 9);
}
else
this.cursor = this.prev_cursor;
}
else
if this.cursor - BUTTON_COL > -1;
this.cursor -= BUTTON_COL;
}
this.cursor_delay->undo();
}
elseif state[CPI_SCANCODE_DOWN];
if this.cursor_delay->do() {
if this.cursor > -1 {
if this.cursor + BUTTON_COL < BUTTON_COUNT {
this.cursor += BUTTON_COL;
else
this.prev_cursor = this.cursor;
var col int = this.cursor % BUTTON_COL;
if col >= 0 and col <= 1 {
this.cursor = TAB;
elseif col >= 2 and col <= 3;
this.cursor = SHIFT;
elseif col >= 4 and col <= 8;
this.cursor = SPACE;
if this.enable_return {
if col >= 7 and col <= 8;
this.cursor = RETURN;
}
else
this.cursor = BACKSPACE;
}
}
}
this.cursor_delay->undo();
}
elseif state[CPI_SCANCODE_A];
if this.remove_delay->do() {
this->remove(render);
this.remove_delay->undo();
}
elseif state[CPI_SCANCODE_LK1];
if this.cursor_delay->do() {
this->move_caret(true);
this.cursor_delay->undo();
}
elseif state[CPI_SCANCODE_LK5];
if this.cursor_delay->do() {
this->move_caret(false);
this.cursor_delay->undo();
}
// CPI_SCANCODE_LK2
// CPI_SCANCODE_LK4
else
this.cursor_delay->reset();
this.remove_delay->reset();
}
if state[CPI_SCANCODE_MENU] {
if this.input_lock->do() {
this->close();
}
elseif state[CPI_SCANCODE_SELECT];
if this.input_lock->do() {
if this.mode == 2 {
this.mode = this.prev_mode;
this.lock = this.prev_lock;
this.enable_shift = true;
else
this.prev_mode = this.mode;
this.prev_lock = this.lock;
this.mode = 2;
this.lock = false;
this.enable_shift = false;
}
}
elseif state[CPI_SCANCODE_START];
if this.input_lock->do() {
this->done();
}
elseif state[CPI_SCANCODE_B];
if this.input_lock->do() {
if this.cursor < 0 {
if this.cursor == SHIFT {
this->toggle_shift();
elseif this.cursor == BACKSPACE;
this->remove(render);
elseif this.cursor == SPACE;
this->insert_char(render, ' ');
elseif this.cursor == TAB;
this->insert_char(render, '\t');
elseif this.cursor == RETURN;
this->insert_char(render, '\n');
}
else
var pressed char = layout[this.mode, this.cursor];
if pressed {
if this.mode == 1 {
if !this.lock;
this.mode = 0;
}
this->insert_char(render, pressed);
}
}
}
elseif state[CPI_SCANCODE_X];
if this.input_lock->do() {
this->toggle_shift();
}
elseif state[CPI_SCANCODE_Y];
if this.input_lock->do() {
this->insert_char(render, ' ');
}
elseif state[CPI_SCANCODE_SHIFT_SELECT];
if this.input_lock->do() {
var wnd. window = this->get_window();
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
browser->set_callback(
lambda(filename. char, this.keybd) [
this->insert(this->get_window()->get_render(), filename);
], null, this
);
browser->set_fadeout(&this.fadeio);
if browser->set_dir(wnd->get_render(), "/home/cpi") or
browser->set_dir(wnd->get_render(), "/") {
browser->set_mode(
scene::file_browser::mode.select);
wnd->push_scene(this);
wnd->set_scene(browser);
else
wnd->free_scene(browser);
}
}
else
this.input_lock->set(false);
}
}
private func draw_button(render void, index int, rect. SDL_Rect, tex. texture, custom_color bool = false) {
var focus bool = index == this.cursor;
if !custom_color {
if focus {
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
else
SDL_SetRenderDrawColor(render, 235, 235, 235, 0xff);
}
}
SDL_RenderFillRect(render, rect);
if focus {
SDL_SetRenderDrawColor(render, 0, 162, 232, 0xff);
SDL_RenderDrawRect(render, rect);
else
SDL_SetRenderDrawColor(render, 127, 127, 127, 0xff);
SDL_RenderDrawRect(render, rect);
}
tex->draw(render,
rect.x + (rect.w - tex->get_width()) / 2,
rect.y + (rect.h - tex->get_height()) / 2);
}
func draw(render void) {
define {
TITLE_X = 10;
TITLE_Y = 10;
TEXT_Y = 45;
KEYBD_Y = 85;
}
SDL_SetRenderDrawColor(render, 245, 245, 245, 0xff);
SDL_RenderClear(render);
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
// title
this.tex.title->draw(render, TITLE_X, TITLE_Y);
using caret_x int {
// text
if this.tex.text->get_texture() == null {
caret_x = rect.w / 2;
else
var width int = this.tex.text->get_width();
if width > (rect.w - TEXT_GAP) {
var x int = (TEXT_GAP / 2);
caret_x = x + (this.caret_x - this.start_x);
this.tex.text->draw(render, x + -this.start_x, TEXT_Y);
else
var x int = (rect.w - width) / 2;
caret_x = x + this.caret_x;
this.tex.text->draw(render, x, TEXT_Y);
}
}
// caret
if this.draw_caret {
SDL_SetRenderDrawColor(render, 125, 125, 125, 0xff);
SDL_RenderDrawLine(render, caret_x, TEXT_Y, caret_x,
TEXT_Y + global::uni_font->get_height());
}
}
// keybd
var sub_rect SDL_Rect;
var x int = (rect.w - ((BUTTON_COL * (BUTTON_WIDTH + BUTTON_GAP)) - BUTTON_GAP)) / 2;
var y int = KEYBD_Y;
forvar index int = 0; index < BUTTON_COUNT; index++ {
sub_rect.x = x + ((index % BUTTON_COL) * (BUTTON_WIDTH + BUTTON_GAP));
sub_rect.y = y + ((index / BUTTON_COL) * (BUTTON_HEIGHT + BUTTON_GAP));
sub_rect.w = BUTTON_WIDTH;
sub_rect.h = BUTTON_HEIGHT;
this->draw_button(render, index, &sub_rect,
&singleton::ascii[layout[this.mode, index]]);
}
sub_rect.x = x;
sub_rect.y += BUTTON_WIDTH + BUTTON_GAP;
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
sub_rect.h = BUTTON_HEIGHT;
this->draw_button(render, TAB, &sub_rect,
&singleton::tab);
sub_rect.x += sub_rect.w + BUTTON_GAP;
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
sub_rect.h = BUTTON_HEIGHT;
{
var custom_color bool = false;
var tex. texture = &singleton::shift;
if this.enable_shift {
if this.mode == 1 {
if this.lock {
tex = &singleton::shift_white;
SDL_SetRenderDrawColor(render, 130, 130, 130, 0xff);
else
SDL_SetRenderDrawColor(render, 205, 205, 205, 0xff);
}
custom_color = true;
}
else
SDL_SetRenderDrawColor(render, 165, 165, 165, 0xff);
custom_color = true;
}
this->draw_button(render, SHIFT, &sub_rect, tex, custom_color);
}
SDL_SetRenderDrawColor(render, 205, 205, 205, 0xff);
if this.enable_return {
sub_rect.x += sub_rect.w + BUTTON_GAP;
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 3) - BUTTON_GAP;
sub_rect.h = BUTTON_HEIGHT;
this->draw_button(render, SPACE, &sub_rect,
&singleton::space, true);
sub_rect.x += sub_rect.w + BUTTON_GAP;
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
sub_rect.h = BUTTON_HEIGHT;
this->draw_button(render, RETURN, &sub_rect,
&singleton::ret);
else
sub_rect.x += sub_rect.w + BUTTON_GAP;
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 5) - BUTTON_GAP;
sub_rect.h = BUTTON_HEIGHT;
this->draw_button(render, SPACE, &sub_rect,
&singleton::space, true);
}
sub_rect.x += sub_rect.w + BUTTON_GAP;
sub_rect.w = ((BUTTON_WIDTH + BUTTON_GAP) * 2) - BUTTON_GAP;
sub_rect.h = BUTTON_HEIGHT;
this->draw_button(render, BACKSPACE, &sub_rect,
&singleton::backspace);
this.fadeio->do();
}
func wake() {
this.caret_timer->done();
this.cursor_delay->reset(false);
this.remove_delay->reset(false);
this.input_lock->set(true);
}
}

View File

@@ -1,130 +0,0 @@
class game+, scene+, main+, status_bar {
inherit game::control = super;
private import rt::c, lib::sdl2;
struct status_bar {
long_timer delay;
short_timer delay;
batt_icon(4) texture;
batt_charging_icon texture;
batt_cap int;
wifi_icon(4) texture;
wifi_sig int;
colon bool;
}
func constructor() {
constructor(this);
this.batt_cap = -1;
this.wifi_sig = -1;
this.colon = true;
}
func destructor() {
destructor(this);
}
define {
BATT_UNKNOWN = 0;
BATT_LOW = 1;
BATT_MID = 2;
BATT_FULL = 3;
}
define {
WIFI_OFF = 0;
WIFI_LOW = 1;
WIFI_MID = 2;
WIFI_HIGH = 3;
}
func init(render void) bool {
this.long_timer->init(3000);
this.long_timer->done();
this.short_timer->init(1000);
this.short_timer->done();
this.batt_icon[BATT_UNKNOWN]->load_file(render,
global::make_path("main/battery.png"));
this.batt_icon[BATT_LOW]->load_file(render,
global::make_path("main/battery_low.png"));
this.batt_icon[BATT_MID]->load_file(render,
global::make_path("main/battery_mid.png"));
this.batt_icon[BATT_FULL]->load_file(render,
global::make_path("main/battery_full.png"));
this.batt_charging_icon->load_file(render,
global::make_path("main/battery_charging.png"));
this.wifi_icon[WIFI_OFF]->load_file(render,
global::make_path("main/wifi.png"));
this.wifi_icon[WIFI_LOW]->load_file(render,
global::make_path("main/wifi_low.png"));
this.wifi_icon[WIFI_MID]->load_file(render,
global::make_path("main/wifi_mid.png"));
this.wifi_icon[WIFI_HIGH]->load_file(render,
global::make_path("main/wifi_high.png"));
return true;
}
func update(render void) {
if this.long_timer->do() {
if !global::wifi->is_connected(&this.wifi_sig);
this.wifi_sig = -1;
this.long_timer->undo();
}
if this.short_timer->do() {
this.batt_cap = global::get_battery_cap();
this.colon = !this.colon;
this.short_timer->undo();
}
}
private func get_batt_icon() .texture {
var icon int = BATT_UNKNOWN;
if this.batt_cap ~= -1 {
var cap int = this.batt_cap & ~0x100;
if cap > 65 {
icon = BATT_FULL;
elseif cap > 20;
icon = BATT_MID;
elseif cap > 0;
icon = BATT_LOW;
}
}
return &this.batt_icon[icon];
}
private func get_wifi_icon() .texture {
var icon int;
if this.wifi_sig > 60 {
icon = WIFI_HIGH;
elseif this.wifi_sig > 30;
icon = WIFI_MID;
elseif this.wifi_sig > 0;
icon = WIFI_LOW;
else
icon = WIFI_OFF;
}
return &this.wifi_icon[icon];
}
func draw(render void) {
var x int = this->get_right();
var y int = this->get_y();
using batt_icon. texture = this->get_batt_icon() {
if this.batt_cap ~= -1;
global::small_font->draw_cap(render, x -= 40, y + 7, this.batt_cap & ~0x100);;
batt_icon->draw(render, x -= batt_icon->get_width(), y);
if this.batt_cap ~= -1 and
this.batt_cap & 0x100;
this.batt_charging_icon->draw(render, x, y);
}
using wifi_icon. texture = this->get_wifi_icon() {
wifi_icon->draw(render, x -= wifi_icon->get_width(), y);
}
global::small_font->draw_time(render,
x -= 55, y + 7, time(null), this.colon);
}
}

View File

@@ -1,168 +0,0 @@
/*
set_callback(on_press void, arg void)
add_menu(render void, id int, title. char, icon_filename. char) bool
set_cursor(cursor int)
get_selected_menu() .menu
*/
class game+, scene+, main+, sub_menu {
inherit game::control = super;
private import rt::c, lib::sdl2;
class menu {
struct menu {
icon texture;
title texture;
id int;
}
func constructor() {
constructor(this); }
func destructor() {
destructor(this); }
}
struct sub_menu {
struct tex {
button texture;
button_hover texture;
}
menus(MENU_COUNT) menu;
menu_count int;
input_delay repeat;
input_lock norepeat;
cursor int;
on_press void;
arg void;
}
func constructor() {
memset(this, 0, sizeof(sub_menu));
constructor(this);
}
func destructor() {
destructor(this);
}
define {
MENU_COUNT = 5;
BUTTON_WIDTH = 40;
BUTTON_HEIGHT = 40;
BUTTON_GAP = 10;
}
func init(render void) bool {
this.tex.button->load_file(render,
global::make_path("main/button_40x40.png"));
this.tex.button_hover->load_file(render,
global::make_path("main/button_hover_40x40.png"));
this.input_delay->init(300, -10, 20);
return true;
}
inline set_callback(on_press void, arg void) {
this.on_press = on_press;
this.arg = arg;
}
func add_menu(render void, id int, title. char, icon_filename. char) bool {
if this.menu_count >= MENU_COUNT;
return false;
this.menus[this.menu_count].icon->load_file(render, icon_filename);
this.menus[this.menu_count].title->init(
global::uni_font->create_tex(render, title, 0xff000000));
this.menus[this.menu_count].id = id;
this.menu_count++;
return true;
}
func update(render void) {
if this->has_focus() {
var state. uint8 = SDL_GetKeyboardState(null);
if state[CPI_SCANCODE_LEFT] {
if this.input_delay->do() {
if this.cursor;
this.cursor--;
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_RIGHT];
if this.input_delay->do() {
if this.cursor < MENU_COUNT - 1;
this.cursor++;
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_UP];
var parent. scene::main = this->get_parent();
var cursor int = this.cursor;
#if MENU_COUNT > tile_menu::TILE_HALF_COUNT;
cursor /= (MENU_COUNT / tile_menu::TILE_HALF_COUNT);
#else
cursor += (tile_menu::TILE_HALF_COUNT - MENU_COUNT) / 2;
#endif
if (cursor += tile_menu::TILE_HALF_COUNT) >= tile_menu::TILE_COUNT;
cursor = tile_menu::TILE_COUNT - 1;
var tile_menu. tile_menu = parent.tile_menu;
tile_menu->set_cursor(cursor);
tile_menu->wake();
parent->set_focus(tile_menu);
else
this.input_delay->reset();
}
if state[CPI_SCANCODE_B] {
if this.input_lock->do() {
var menu. menu = this->get_selected_menu();
if menu ~= null {
proto fn(id int, arg void);
fn[this.on_press](menu.id, this.arg);
}
}
else
this.input_lock->set(false);
}
}
}
func draw(render void) {
var focus bool = this->has_focus();
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
var x int = this->get_x() +
(this->get_width() - ((BUTTON_WIDTH * MENU_COUNT) + (BUTTON_GAP * (MENU_COUNT - 1)))) / 2;
var y int = this->get_y();
forvar index int = 0; index < MENU_COUNT; index++ {
var menu. menu = &this.menus[index];
if focus and this.cursor == index {
this.tex.button_hover->draw(render, x, y);
// out of bounds
menu.title->draw(render,
this->get_x() + (rect.w - menu.title->get_width()) / 2,
y - (menu.title->get_height() + 4));
else
this.tex.button->draw(render, x, y);
}
menu.icon->draw(render, x + 1, y + 1);
x += (BUTTON_WIDTH + BUTTON_GAP);
}
}
func wake() {
this.input_delay->reset(false);
this.input_lock->set(true);
}
//
inline set_cursor(cursor int) {
this.cursor = cursor;
}
inline get_selected_menu() .menu {
if this.cursor < this.menu_count;
return &this.menus[this.cursor];
return null;
}
}

View File

@@ -1,635 +0,0 @@
/*
reload_page(render void)
set_mode(mode. mode)
get_mode() mode
set_link(filename. char)
clear_link()
get_page() int
set_page(render void, page int)
set_cursor(cursor int)
get_app(index int) .tile_app
get_selected_app() .tile_app
*/
class game+, scene+, main+, tile_menu {
inherit game::control = super;
private import rt::c, lib::sdl2;
private alias
string = std::string,
strings = std::strings;
private alias popup_menu = control::popup_menu;
enum mode {
none,
move,
link
}
class image_cache {
private import rt::c;
private alias
vector = std::vector,
string = std::string;
struct cache {
filename string;
tex texture;
}
struct image_cache {
caches vector<cache>;
}
func constructor() {
constructor(this); }
func destructor() {
destructor(this); }
func find(filename. char) .cache {
var count size_t = this.caches->count();
while count {
var cache. cache = this.caches->at(--count);
if !strcmp(cache.filename->ptr(), filename) {
return cache;
}
}
return null;
}
func load_file(render void, filename. char) void {
var cache. cache = this->find(filename);
if cache == null {
cache = this.caches->new();
cache.filename->set(filename);
if !cache.tex->load_file(render, filename) {
this.caches->pop_back();
return null;
}
}
return cache.tex->get_texture();
}
}
/*
fixme
*/
class tile_app {
struct tile_app {
struct tex {
icon texture;
title texture;
}
icon. char;
title. char;
cmd. char;
slot int;
type int;
}
func constructor() {
constructor(this); }
func destructor() {
destructor(this); }
}
struct tile_menu {
struct tex {
tile texture;
tile_hover texture;
// ...
move_mode texture;
link_mode texture;
}
input_delay repeat;
input_lock norepeat;
page int;
cursor int;
struct slide {
delay delay;
dir bool;
}
image_cache image_cache;
apps(TILE_COUNT) tile_app;
temp_apps(TILE_COUNT) tile_app;
moving_icon texture;
mode mode;
from int;
link string;
}
func constructor() {
memset(this, 0, sizeof(tile_menu));
constructor(this);
}
func destructor() {
destructor(this);
}
define {
TILE_COUNT = 10;
TILE_HALF_COUNT = TILE_COUNT / 2;
TILE_WIDTH = 52;
TILE_HEIGHT = 52;
TILE_GAP = 10;
}
define {
MAX_PAGE = 10;
}
static func free_app(app. tile_app) {
app.tex.icon->destroy();
app.tex.title->destroy();
app.icon = null;
app.title = null;
app.cmd = null;
app.type = -1;
}
func reload_page(render void) {
struct args {
tile_menu. tile_menu;
tile_apps. tile_app;
render void;
begin int;
}
var arg args;
arg.tile_menu = this;
arg.tile_apps = &this.apps;
arg.render = render;
arg.begin = (this.page - 1) * TILE_COUNT;
forvar i int = 0; i < TILE_COUNT; i++ {
var app. tile_app = &this.apps[i];
this->free_app(app);
app.slot = arg.begin + i;
}
global::apps->for_each(arg.begin, arg.begin + (TILE_COUNT - 1),
lambda(app. app_list::app, arg. args) [
var tile_menu. tile_menu = arg.tile_menu;
var tile_app. tile_app = &arg.tile_apps[app.slot - arg.begin];
tile_app.tex.icon->init(
tile_menu.image_cache->load_file(arg.render,
tile_app.icon = app.icon->ptr()), false);
using title void {
tile_app.title = app.title->ptr();
// deprecated
if global::outlined_font {
title = global::uni_font->create_outlined_tex(arg.render, tile_app.title,
0xffffffff, 0xff000000, 1);
else
title = global::uni_font->create_tex(arg.render, tile_app.title, 0xff000000);
}
tile_app.tex.title->init(title);
}
tile_app.cmd = app.cmd->ptr();
tile_app.type = app.type;
], &arg
);
}
func init(render void) bool {
this.tex.tile->load_file(render,
global::make_path("main/tile_52x52.png"));
this.tex.tile_hover->load_file(render,
global::make_path("main/tile_hover_52x52.png"));
// ...
this.tex.move_mode->init(
global::uni_font->create_tex(render, "Move Mode", 0xffffffff));
this.tex.link_mode->init(
global::uni_font->create_tex(render, "Link Mode", 0xffffffff));
this.input_delay->init(300, -25, 10);
this.slide.delay->done();
this.page = 1;
this->reload_page(render);
return true;
}
private func exec(cmd. char) {
if .cmd == '#' {
var strs strings;
strs->split(++cmd, "\t");
/*
#exec dir ext format
*/
if !strcmp(strs->first_item(), "exec") {
if strs->count() > 3 {
var wnd. window = this->get_window();
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
browser->set_fadeout(&this->get_parent_t<scene::main>().fadeio);
browser->hidden_files(true);
browser->set_mode(
scene::file_browser::mode.exec);
if strlen(strs->item(2));
browser->set_ext(strs->item(2));
browser->set_exec_format(strs->item(3));
mkdir(strs->item(1), 0775);
if browser->set_dir(wnd->get_render(), strs->item(1), true) {
wnd->push_scene(this->get_parent());
wnd->set_scene(browser);
else
wnd->free_scene(browser);
}
}
}
elseif .cmd;
exec3(this->get_window(), "Please Wait", cmd);
}
}
// popup
private func adjust_popup_pos(popup. popup_menu) {
var x int = this->get_x() + TILE_GAP;
var y int = this->get_y();
if this.cursor < TILE_HALF_COUNT {
x += this.cursor * (TILE_WIDTH + TILE_GAP);
else
x += (this.cursor - TILE_HALF_COUNT) * (TILE_WIDTH + TILE_GAP);
y += TILE_HEIGHT + TILE_GAP;
}
x += TILE_WIDTH;
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
var popup_width int = popup->get_width();
var popup_height int = popup->get_height();
if (x + popup_width) > rect.w;
x -= popup_width + TILE_WIDTH;
if (y + popup_height) > rect.h;
y = rect.h - popup_height;
popup->set_pos(x, y);
}
private func show_edit_popup(render void, app. tile_app) {
define {
POPUP_WIDTH = 280;
POPUP_HEIGHT = 186;
}
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
this->close_popup();
var popup. edit_popup = this->create_control<edit_popup>(
(rect.w - POPUP_WIDTH) / 2,
(rect.h - POPUP_HEIGHT) / 2, POPUP_WIDTH, POPUP_HEIGHT);
popup->fill_in(render, app);
this->set_popup(popup);
}
private func show_popup(render void, app. tile_app) {
define {
MENU_REMOVE = -1;
MENU_EXECUTE = 0;
MENU_MOVE = 1;
MENU_EDIT = 2;
}
this->close_popup();
var popup. popup_menu = this->create_control<popup_menu>(0, 0);
popup->set_callback(
lambda(id int, this.tile_menu) [
var app. tile_app = this->get_selected_app();
if id == MENU_REMOVE {
if global::apps->remove(app.slot);
this->free_app(app);
elseif id == MENU_EXECUTE;
if app.cmd ~= null;
this->exec(app.cmd);
elseif id == MENU_MOVE;
var render void = this->get_window()->get_render();
this.from = app.slot;
this.moving_icon->init(
this.image_cache->load_file(render, app.icon), false);
this.mode = mode.move;
elseif id == MENU_EDIT;
this->show_edit_popup(this->get_window()->get_render(), app);
}
],
lambda(this.tile_menu) [
this->close_popup();
], this);
if app.type == -1 {
popup->add_menu(render, MENU_EDIT, "Edit");
else
popup->add_menu(render, MENU_EXECUTE, "Execute");
popup->add_menu(render, MENU_MOVE, "Move");
if app.type {
popup->add_menu(render, MENU_EDIT, "Edit");
popup->add_menu(render, MENU_REMOVE, "Remove");
}
}
this->adjust_popup_pos(popup);
this->set_popup(popup);
}
//
private func try_slide(render void, cursor int, page int, dir bool, delay int = 300) {
if this.slide.delay->done?() {
this.cursor = cursor;
this.page = page;
this.temp_apps = this.apps;
memset(&this.apps, 0, sizeof(tile_app, TILE_COUNT));
this->reload_page(render);
this.slide.dir = dir;
this.slide.delay->init(delay);
this->get_window()->enable_turbo(delay * 2);
}
}
func update(render void) {
if this->has_focus() {
if this->has_popup() {
this.super->update(render);
else
var state. uint8 = SDL_GetKeyboardState(null);
if state[CPI_SCANCODE_LEFT] {
if this.input_delay->do() {
if !this.cursor {
if this.page > 1 {
this->try_slide(render, TILE_HALF_COUNT - 1, this.page - 1, false);
else
this->try_slide(render, TILE_HALF_COUNT - 1, MAX_PAGE, false);
}
elseif this.cursor == TILE_HALF_COUNT;
if this.page > 1 {
this->try_slide(render, TILE_COUNT - 1, this.page - 1, false);
else
this->try_slide(render, TILE_COUNT - 1, MAX_PAGE, false);
}
elseif this.cursor;
this.cursor--;
}
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_RIGHT];
if this.input_delay->do() {
if this.cursor == TILE_HALF_COUNT - 1 {
if this.page < MAX_PAGE {
this->try_slide(render, 0, this.page + 1, true);
else
this->try_slide(render, 0, 1, true);
}
elseif this.cursor == TILE_COUNT - 1;
if this.page < MAX_PAGE {
this->try_slide(render, TILE_HALF_COUNT, this.page + 1, true);
else
this->try_slide(render, TILE_HALF_COUNT, 1, true);
}
elseif this.cursor < TILE_COUNT - 1;
this.cursor++;
}
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_UP];
if this.input_delay->do() {
if this.cursor >= TILE_HALF_COUNT;
this.cursor -= TILE_HALF_COUNT;
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_DOWN];
if this.input_delay->do() {
if this.cursor < TILE_HALF_COUNT {
this.cursor += TILE_HALF_COUNT;
elseif this.mode == mode.none;
var parent. scene::main = this->get_parent();
var cursor int = this.cursor - TILE_HALF_COUNT;
#if TILE_HALF_COUNT > sub_menu::MENU_COUNT;
cursor /= (TILE_HALF_COUNT / sub_menu::MENU_COUNT);
#else
cursor += (sub_menu::MENU_COUNT - TILE_HALF_COUNT) / 2;
#endif
if cursor >= sub_menu::MENU_COUNT;
cursor = sub_menu::MENU_COUNT - 1;
var sub_menu. sub_menu = parent.sub_menu;
sub_menu->set_cursor(cursor);
sub_menu->wake();
parent->set_focus(sub_menu);
}
this.input_delay->undo();
}
else
this.input_delay->reset();
}
if state[CPI_SCANCODE_A] {
if this.input_lock->do() {
if this.mode == mode.move {
this.mode = mode.none;
this.moving_icon->destroy();
elseif this.mode == mode.link;
this.mode = mode.none;
this.link->clear();
}
}
elseif state[CPI_SCANCODE_B];
if this.input_lock->do() {
if this.mode == mode.none {
var app. tile_app = this->get_selected_app();
if app.cmd ~= null {
this->exec(app.cmd);
}
elseif this.mode == mode.move;
var app. tile_app = this->get_selected_app();
if app.slot == this.from {
this.mode = mode.none;
this.moving_icon->destroy();
else
if app.type {
if global::apps->move(this.from, app.slot);
this->reload_page(render);
this.mode = mode.none;
this.moving_icon->destroy();
else
// system app
}
}
elseif this.mode == mode.link;
var app. tile_app = this->get_selected_app();
if app.type == -1 {
app.cmd = this.link->ptr();
this->show_edit_popup(render, app);
this.mode = mode.none;
}
}
}
elseif state[CPI_SCANCODE_MENU];
if this.input_lock->do() {
if this.mode == mode.none;
this->show_popup(render, this->get_selected_app());
}
elseif state[CPI_SCANCODE_LK1];
if this.input_lock->do() {
if this.page > 1 {
this->try_slide(render, this.cursor, this.page - 1, false);
else
this->try_slide(render, this.cursor, MAX_PAGE, false);
}
}
elseif state[CPI_SCANCODE_LK5];
if this.input_lock->do() {
if this.page < MAX_PAGE {
this->try_slide(render, this.cursor, this.page + 1, true);
else
this->try_slide(render, this.cursor, 1, true);
}
}
else
this.input_lock->set(false);
}
}
}
}
private func draw_icon(render void, icon. texture, rect. SDL_Rect) {
var width int = icon->get_width();
var height int = icon->get_height();
if width > rect.w;
width = rect.w;
if height > rect.h;
height = rect.h;
icon->draw3(render,
rect.x + (rect.w - width) / 2,
rect.y + (rect.h - height) / 2, width, height);
}
private func draw_tiles(render void, x int, y int, start int, end int) {
var rect SDL_Rect;
rect.y = y + 1;
rect.w = TILE_WIDTH - 2;
rect.h = TILE_HEIGHT - 2;
forvar index int = start; index < end; index++ {
var app. tile_app = &this.apps[index];
rect.x = x + 1;
if this->has_focus() and this.cursor == index {
this.tex.tile_hover->draw(render, x, y);
if this.moving_icon->get_texture() == null {
this->draw_icon(render, &app.tex.icon, &rect);
else
this->draw_icon(render, &this.moving_icon, &rect);
}
// out of bounds
app.tex.title->draw(render,
this->get_x() + (this->get_width() - app.tex.title->get_width()) / 2,
this->get_bottom() + 5);
else
this.tex.tile->draw(render, x, y);
this->draw_icon(render,
&app.tex.icon, &rect);
}
x += (TILE_GAP + TILE_WIDTH);
}
}
private func draw_temp_tiles(render void, x int, y int, start int, end int) {
var rect SDL_Rect;
rect.y = y + 1;
rect.w = TILE_WIDTH - 2;
rect.h = TILE_HEIGHT - 2;
forvar index int = start; index < end; index++ {
this.tex.tile->draw(render, x, y);
rect.x = x + 1;
this->draw_icon(render, &this.temp_apps[index].tex.icon, &rect);
x += (TILE_GAP + TILE_WIDTH);
}
}
private func slide(render void) int {
if this.slide.delay->do() {
forvar index int = 0; index < TILE_COUNT; index++;
this->free_app(&this.temp_apps[index]);
return 0;
}
var delta int = this.slide.delay->get_per_r<int>(this->get_width());
if this.slide.dir {
this->draw_temp_tiles(render,
this->get_x() - delta + TILE_GAP,
this->get_y(), 0, TILE_HALF_COUNT);
this->draw_temp_tiles(render,
this->get_x() - delta + TILE_GAP,
this->get_y() + (TILE_GAP + TILE_HEIGHT), TILE_HALF_COUNT, TILE_COUNT);
return this->get_width() - delta;
else
this->draw_temp_tiles(render,
this->get_x() + delta + TILE_GAP,
this->get_y(), 0, TILE_HALF_COUNT);
this->draw_temp_tiles(render,
this->get_x() + delta + TILE_GAP,
this->get_y() + (TILE_GAP + TILE_HEIGHT), TILE_HALF_COUNT, TILE_COUNT);
return -(this->get_width() - delta);
}
}
func draw(render void) {
var delta int = this->slide(render);
this->draw_tiles(render,
this->get_x() + TILE_GAP + delta,
this->get_y(), 0, TILE_HALF_COUNT);
this->draw_tiles(render,
this->get_x() + TILE_GAP + delta,
this->get_y() + (TILE_GAP + TILE_HEIGHT), TILE_HALF_COUNT, TILE_COUNT);
this.super->draw(render);
// out of bounds
if this.mode ~= mode.none {
define {
PADDING = 3;
}
var tex. texture;
if this.mode == mode.move {
tex = &this.tex.move_mode;
elseif this.mode == mode.link;
tex = &this.tex.link_mode;
}
var rect SDL_Rect;
rect.x = 0;
rect.y = 0;
rect.w = tex->get_width() + (PADDING * 2);
rect.h = tex->get_height() + (PADDING * 2);
SDL_SetRenderDrawColor(render, 52, 152, 219, 0xff);
SDL_RenderFillRect(render, &rect);
tex->draw(render, PADDING, PADDING);
}
}
func wake() {
this.input_delay->reset(false);
this.input_lock->set(true);
this.super->wake();
}
//
inline set_mode(mode. mode) {
this.mode = mode;
}
inline get_mode() mode {
return this.mode;
}
inline set_link(filename. char) {
this.link->set(filename);
}
inline clear_link() {
this.link->clear();
}
inline get_page() int {
return this.page;
}
inline set_page(render void, page int) {
this.page = page;
this->reload_page(render);
}
inline set_cursor(cursor int) {
this.cursor = cursor;
}
inline get_app(index int) .tile_app {
return &this.apps[index];
}
inline get_selected_app() .tile_app {
return this->get_app(this.cursor);
}
}

View File

@@ -1,160 +0,0 @@
class game+, scene+, main+ {
inherit game::scene = super;
private import rt::c, lib::sdl2;
private alias vector = std::vector;
struct main {
struct tex {
background texture;
}
fadeio fadeio;
input_lock norepeat;
status_bar. status_bar;
tile_menu. tile_menu;
sub_menu. sub_menu;
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
private func standby() bool {
var level byte = global::get_backlight_level();
if level == -1;
return false;
if !global::set_backlight_level(0);
return false;
lambda signal(pids. vector<int>, sig int) [
var count size_t = pids->count();
while count {
var pid int = .pids->at(--count);
if pid ~= -1;
kill(pid, sig);
}
];
var pids vector<int>;
pids->push_back(find_pid_by_cmdline("/home/cpi/launcher/sys.py/gsnotify/gsnotify-arm"));
signal(&pids, SIGTSTP);
for ;; {
var event SDL_Event;
while SDL_PollEvent(&event) {
if event.type == SDL_KEYDOWN {
break 2;
elseif event.type == SDL_QUIT;
this->get_window()->quit();
break 2;
}
}
sleep(3);
}
signal(&pids, SIGCONT);
forvar attempt int = 0; attempt < 3; attempt++ {
if global::set_backlight_level(level);
break;
sleep(1);
}
return true;
}
func init(render void) bool {
var wnd. window = this->get_window();
var rect SDL_Rect = 0;
wnd->get_size(&rect.w, &rect.h);
this.tex.background->load_file(render,
global::make_path("main/background.png"));
this.fadeio->init(wnd, 300);
this.fadeio->set_texture(wnd->screen_capture2());
// 1st
this.tile_menu = this->new_control<tile_menu>(0, 36, rect.w, 114);
define {
MENU_NONE = 1;
MENU_BROWSER = 2;
MENU_STANDBY = 3;
MENU_QUIT = 4;
}
// 2nd
this.sub_menu = this->new_control<sub_menu>(0, 176, rect.w, 40);
this.sub_menu->set_callback(
lambda(id int, this.main) [
if id == MENU_BROWSER {
var wnd. window = this->get_window();
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
browser->set_fadeout(&this.fadeio);
browser->set_mode(
scene::file_browser::mode.browse);
var cwd(0x800) char;
if getcwd(&cwd, sizeof(cwd)) ~= null and browser->set_dir(wnd->get_render(), &cwd) {
wnd->push_scene(this);
wnd->set_scene(browser);
else
wnd->free_scene(browser);
}
elseif id == MENU_STANDBY;
this->standby();
elseif id == MENU_QUIT;
this->get_window()->quit();
}
], this
);
this.sub_menu->add_menu(render, MENU_BROWSER, "File Browser",
global::make_path("main/browser.png"));
this.sub_menu->add_menu(render, MENU_STANDBY, "Standby",
global::make_path("main/standby.png"));
this.sub_menu->add_menu(render, MENU_QUIT, "Quit",
global::make_path("main/quit.png"));
// 3rd
this.status_bar = this->new_control<status_bar>(8, 4, rect.w - 16, 26);
this->set_focus(this.tile_menu);
return true;
}
func update(render void) {
this.super->update(render);
var state. uint8 = SDL_GetKeyboardState(null);
if state[CPI_SCANCODE_SELECT] {
/*
if this.input_lock->do() {
var cwd(0x800) char;
if getcwd(&cwd, sizeof(cwd)) ~= null {
var filename std::string;
filename->format("%s/bean", &cwd);
execl( filename->ptr(),
filename->ptr(), null);
}
}
*/
else
this.input_lock->set(false);
}
}
func draw(render void) {
if this.tex.background->get_texture() == null {
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(render);
else
this.tex.background->draw(render, 0, 0);
}
var rect SDL_Rect = 0;
this->get_window()->get_size(&rect.w, &rect.h);
// ...
global::small_font->draw_page(render, 8, rect.h - 18,
this.tile_menu->get_page(), tile_menu::MAX_PAGE);
this.super->draw(render);
this.fadeio->do();
}
func wake() {
this.input_lock->set(true);
this.super->wake();
}
}

View File

@@ -1,237 +0,0 @@
/*
fill_in(render void, app. tile_app)
*/
class game+, scene+, main+, edit_popup {
inherit game::control = super;
private import rt::c, lib::sdl2;
private alias string = std::string;
private alias
button = control::button,
edit = control::edit,
image_button = control::image_button,
label = control::label;
private alias tile_app = tile_menu::tile_app;
struct edit_popup {
input_delay repeat;
input_lock norepeat;
new_icon string;
focus_map focus_map;
app. tile_app;
label_title. label;
label_cmd. label;
label_icon. label;
edit_title. edit;
edit_cmd. edit;
button_icon. image_button;
button_cancel. button;
button_save. button;
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
func init(render void) bool {
this.input_delay->init(300, -10, 20);
var rect SDL_Rect = this->get_rect();
var y int = 10;
this.label_title = this->new_control<label>(10, y);
this.label_title->set_text(render, "Title");
this.edit_title = this->new_control<edit>(
10, y += (this.label_title->get_height() + 3), rect.w - 20, 25);
this.label_cmd = this->new_control<label>(
10, y += (this.edit_title->get_height() + 3));
this.label_cmd->set_text(render, "CommandLine");
this.edit_cmd = this->new_control<edit>(
10, y += (this.label_cmd->get_height() + 3), rect.w - 20, 25);
this.label_icon = this->new_control<label>(
10, y += (this.edit_cmd->get_height() + 3));
this.label_icon->set_text(render, "Icon");
this.button_icon = this->new_control<image_button>(
10, y += (this.label_icon->get_height() + 3));
this.button_icon->set_normal_image(render,
global::make_path("main/tile_52x52.png"));
this.button_icon->set_hover_image(render,
global::make_path("main/tile_hover_52x52.png"));
this.button_icon->set_outline_size(1);
define {
BUTTON_WIDTH = 70;
BUTTON_HEIGHT = 30;
}
this.button_cancel = this->new_control<button>(
rect.w - ((BUTTON_WIDTH * 2) + 16),
rect.h - (BUTTON_HEIGHT + 10), BUTTON_WIDTH, BUTTON_HEIGHT);
this.button_cancel->set_text(render, "Cancel");
this.button_save = this->new_control<button>(
rect.w - (BUTTON_WIDTH + 10),
rect.h - (BUTTON_HEIGHT + 10), BUTTON_WIDTH, BUTTON_HEIGHT);
this.button_save->set_text(render, "Save");
this.focus_map->register(this.edit_title, null, this.edit_cmd, null, null);
this.focus_map->register(this.edit_cmd, this.edit_title, this.button_icon, null, null);
this.focus_map->register(this.button_icon, this.edit_cmd, null, null, this.button_cancel);
this.focus_map->register(this.button_cancel, this.edit_cmd, null, this.button_icon, this.button_save);
this.focus_map->register(this.button_save, this.edit_cmd, null, this.button_cancel, null);
this->set_focus(this.edit_title);
return true;
}
func fill_in(render void, app. tile_app) {
this.app = app;
if app.title ~= null;
this.edit_title->set_text(render, app.title);
if app.cmd ~= null;
this.edit_cmd->set_text(render, app.cmd);
if app.icon ~= null;
this.button_icon->set_image(render, app.icon);
}
private func show_keybd(render void, title. char, edit. edit) {
var wnd. window = this->get_window();
var keybd. scene::keybd = wnd->new_scene<scene::keybd>();
keybd->set_callback(edit->get_keybd_cb(), null, edit);
keybd->set_fadeout(&this->get_parent_t<scene::main>().fadeio);
keybd->set_title(render, title);
keybd->set_text(render, edit->get_text());
wnd->push_scene(this->get_parent());
wnd->set_scene(keybd);
}
private func close() {
var parent. tile_menu = this->get_parent_control();
parent->clear_link();
parent->close_popup();
}
func update(render void) {
var state. uint8 = SDL_GetKeyboardState(null);
if state[CPI_SCANCODE_UP] {
if this.input_delay->do() {
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_UP);
if focus ~= null;
this->set_focus(focus);
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_DOWN];
if this.input_delay->do() {
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_DOWN);
if focus ~= null;
this->set_focus(focus);
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_LEFT];
if this.input_delay->do() {
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_LEFT);
if focus ~= null;
this->set_focus(focus);
this.input_delay->undo();
}
elseif state[CPI_SCANCODE_RIGHT];
if this.input_delay->do() {
var focus void = this.focus_map->get(this->get_focus(), CPI_SCANCODE_RIGHT);
if focus ~= null;
this->set_focus(focus);
this.input_delay->undo();
}
else
this.input_delay->reset();
}
if state[CPI_SCANCODE_A] or
state[CPI_SCANCODE_MENU] {
if this.input_lock->do() {
this->close();
}
elseif state[CPI_SCANCODE_B];
if this.input_lock->do() {
var focus void = this->get_focus();
if focus == this.edit_title {
this->show_keybd(render, "Title", this.edit_title);
elseif focus == this.edit_cmd;
this->show_keybd(render, "CommandLine", this.edit_cmd);
elseif focus == this.button_icon;
var wnd. window = this->get_window();
var browser. scene::file_browser = wnd->new_scene<scene::file_browser>();
browser->set_callback(
lambda(filename. char, this.edit_popup) [
var render void = this->get_window()->get_render();
if this.button_icon->set_image(render, filename) {
this.new_icon->set(filename);
else
var app. tile_app = this.app;
this.button_icon->set_image(render, app.icon);
this.new_icon->clear();
}
], null, this
);
browser->set_fadeout(&this->get_parent_t<scene::main>().fadeio);
browser->set_mode(
scene::file_browser::mode.select_image);
var path string;
var cwd(0x800) char;
if getcwd(&cwd, sizeof(cwd)) ~= null and
browser->set_dir(wnd->get_render(), path->format("%s/icons", &cwd)) or
browser->set_dir(wnd->get_render(), &cwd) {
wnd->push_scene(this->get_parent());
wnd->set_scene(browser);
else
wnd->free_scene(browser);
}
elseif focus == this.button_cancel;
this->close();
elseif focus == this.button_save;
var tile_app. tile_app = this.app;
var new_icon. char;
if this.new_icon->empty() {
new_icon = tile_app.icon;
else
new_icon = this.new_icon->ptr();
}
if tile_app.type == -1 {
global::apps->insert(tile_app.slot, 1,
this.edit_title->get_text(),
this.edit_cmd->get_text(), new_icon);
else
global::apps->update(tile_app.slot, tile_app.type,
this.edit_title->get_text(),
this.edit_cmd->get_text(), new_icon);
}
var parent. tile_menu = this->get_parent_control();
parent->reload_page(render);
this->close();
}
}
else
this.input_lock->set(false);
}
this.super->update(render);
}
func draw(render void) {
var rect SDL_Rect = this->get_rect();
SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(render, 245, 245, 245, 230);
SDL_RenderFillRect(render, &rect);
SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(render, 0xcd, 0xcd, 0xcd, 0xff);
SDL_RenderDrawRect(render, &rect);
this.super->draw(render);
}
func wake() {
this.input_delay->reset(false);
this.input_lock->set(true);
this.super->wake();
}
}

View File

@@ -1,40 +0,0 @@
// template
class game+, scene+, temp {
inherit game::scene = super;
private import lib::sdl2;
struct temp {
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
func init(render void) bool {
return true;
}
func update(render void) {
this.super->update(render);
}
func draw(render void) {
SDL_SetRenderDrawColor(render, 0, 0, 0, 0xff);
SDL_RenderClear(render);
this.super->draw(render);
}
func wake() {
this.super->wake();
}
}

View File

@@ -1,17 +0,0 @@
/*
powered by bean 0.382 r388
*/
module app+ {
func main() {
var launcher game::launcher;
launcher->start("BeanShell");
}
}
func main() {
app::main();
}

View File

@@ -1,60 +0,0 @@
module program+ {
private import
rt::c,
lib::sdl2,
lib::sdl2_image,
lib::sdl2_mixer,
lib::sdl2_ttf;
func startup() {
std::init();
if !lib::curl::so::init() or
!lib::dbus::so::init() or
!lib::sdl2::so::init() or
!lib::sdl2_image::so::init() or
!lib::sdl2_mixer::so::init() or
!lib::sdl2_ttf::so::init()or
!lib::sqlite3::so::init() {
exit(1);
}
init_sdl();
srand2(clock(), time(null), getpid());
}
func cleanup() {
quit_sdl();
}
}
module program+ {
func init_sdl() {
if SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0 {
printf("SDL_Init: %s\n", SDL_GetError());
exit(1);
}
if !IMG_Init(IMG_INIT_PNG) {
printf("IMG_Init: %s\n", SDL_GetError());
exit(1);
}
if !Mix_Init(MIX_INIT_MP3) {
printf("Mix_Init: %s\n", SDL_GetError());
exit(1);
}
if TTF_Init() == -1 {
printf("TTF_Init: %s\n", SDL_GetError());
exit(1);
}
}
func quit_sdl() {
TTF_Quit();
Mix_Quit();
IMG_Quit();
SDL_Quit();
}
}

View File

@@ -1,145 +0,0 @@
/*
FIXME
*/
class app_list+ {
private import rt::c;
private alias
string = std::string,
vector = std::vector;
struct app {
slot int;
type int;
title string;
cmd string;
icon string;
extra string;
}
struct app_list {
db database;
apps vector<app>;
}
func constructor() {
constructor(this); }
func destructor() {
destructor(this); }
func init(filename. char) bool {
if !this.db->open(filename);
return false;
this.db->exec(
"
CREATE TABLE IF NOT EXISTS apps (
slot INTEGER PRIMARY KEY,
type INTEGER NOT NULL,
title TEXT NOT NULL,
command TEXT NOT NULL,
icon TEXT,
extra TEXT
);
"
);
var stmt database::stmt;
if !this.db->prepare(&stmt, "SELECT * FROM apps");
return false;
while stmt->step() {
var app. app = this.apps->new();
app.slot = stmt->column_int(0);
app.type = stmt->column_int(1);
app.title->set(stmt->column_text(2));
app.cmd->set(stmt->column_text(3));
app.icon->set(stmt->column_text(4));
app.extra->set(stmt->column_text(5));
}
return true;
}
func for_each(begin int, end int, callback void, arg void) {
forvar i size_t = 0, c size_t = this.apps->count(); i < c; i++ {
var app. app = this.apps->at(i);
if app.slot >= begin and app.slot <= end {
proto fn(app void, arg void);
fn[callback](app, arg);
}
}
}
func get_app_from_vector(slot int) .app {
forvar index size_t = 0, count size_t = this.apps->count(); index < count; index++ {
var app. app = this.apps->at(index);
if app.slot == slot;
return app;
}
return null;
}
func remove_app_from_vector(slot int) bool {
forvar index size_t = 0, count size_t = this.apps->count(); index < count; index++ {
if this.apps->at(index).slot == slot;
return this.apps->erase(index);
}
return false;
}
func insert(slot int, type int, title. char, cmd. char, icon. char = null, extra. char = null) .app {
if !this.db->execf("INSERT INTO apps (slot, type, title, command, icon, extra) VALUES (%d, %d, %Q, %Q, %Q, %Q)",
slot, type, title, cmd, icon, extra) {
return null;
}
func = this.apps->new();
func.slot = slot;
func.type = type;
func.title->set(title);
func.cmd->set(cmd);
func.icon->set(icon);
func.extra->set(extra);
}
func update(slot int, type int, title. char, cmd. char, icon. char = null, extra. char = null) .app {
if !this.db->execf("UPDATE apps SET type=%d, title=%Q, command=%Q, icon=%Q, extra=%Q WHERE slot=%d",
type, title, cmd, icon, extra, slot) {
return null;
}
/*
fixme
*/
if (func = this->get_app_from_vector(slot)) == null;
return;
func.type = type;
func.title->set(title);
func.cmd->set(cmd);
func.icon->set(icon);
func.extra->set(extra);
}
func remove(slot int) bool {
this->remove_app_from_vector(slot);
/*
fixme
*/
return this.db->execf("DELETE FROM apps WHERE slot=%d", slot);
}
func move(from int, to int) bool {
this->remove(to);
if !this.db->execf("UPDATE apps SET slot=%d WHERE slot=%d", to, from) {
/*
fixme
*/
return false;
}
using app. app = this->get_app_from_vector(from) {
if app ~= null {
app.slot = to;
}
}
return true;
}
}

View File

@@ -1,221 +0,0 @@
class cfg {
private import rt::c;
private alias
vector = std::vector,
string = std::string;
struct item {
name string;
value string;
cover char;
}
struct cfg {
items vector<item>;
filename string;
}
func constructor() {
constructor(this);
}
func destructor() {
destructor(this);
}
func open(filename. char) bool {
define {
SIZE_LIMIT = 0x1000000;
}
lambda read(filename. char, file_size& size_t) void [
var stream void = fopen(filename, "rb");
if stream == null;
return null;
defer fclose(stream);
if fseek(stream, 0, SEEK_END) < 0;
return null;
var tail long = ftell(stream);
if tail < 0 or tail > SIZE_LIMIT;
return null;
rewind(stream);
func = malloc(tail);
var offset size_t = 0;
var remain size_t = tail;
while remain {
var size size_t = fread(func + offset, 1, remain, stream);
if ferror(stream) {
free(func);
return null;
}
offset += size;
remain -= size;
}
file_size = offset;
];
var size size_t;
var buf. char = read(filename, size);
if buf == null;
return false;
defer free(buf);
this.items->clear();
this.filename->clear();
lambda skip_space(buf. char, index& size_t, size size_t) bool [
for ; index < size; index++ {
if !isspace(buf[index]) {
return true;
}
}
return false;
];
lambda skip_line(buf. char, index& size_t, size size_t, end& size_t) bool [
for ; index < size; index++ {
var c char = buf[index];
if c == '\r' {
end = index;
if ++index < size {
if buf[index] == '\n' {
index++;
return true;
}
else
return false;
}
elseif c == '\n';
end = index++;
return true;
}
}
end = index;
return false;
];
lambda skip_name(buf. char, index& size_t, size size_t) bool [
for ; index < size; index++ {
var c char = buf[index];
if c == ' ' or c == '\t' or c == '\r' or c == '\n' or c == '=' {
return true;
}
}
return false;
];
lambda skip_until(buf. char, index& size_t, size size_t, end char) bool [
for ; index < size; index++ {
if buf[index] == end {
return true;
}
}
return false;
];
forvar index size_t = 0 ;; {
if !skip_space(buf, index, size);
break;
var name_offset size_t = index;
if !skip_name(buf, index, size);
break;
var name_size size_t = index - name_offset;
if !name_size;
return false;
if buf[index] ~= '=' {
if !skip_space(buf, ++index, size);
break;
if buf[index] ~= '=';
return false;
}
if !skip_space(buf, ++index, size);
break;
var value_offset size_t;
var value_size size_t;
var cover char;
if buf[index] == '\'' or
buf[index] == '\"' {
cover = buf[index];
value_offset = ++index;
if !skip_until(buf, index, size, cover);
break;
value_size = index++ - value_offset;
else
value_offset = index;
var end size_t;
skip_line(buf, index, size, end);
value_size = end - value_offset;
cover = 0;
}
var item. item = this.items->new();
item.name->set(buf + name_offset, name_size);
if value_size;
item.value->set(buf + value_offset, value_size);
item.cover = cover;
}
this.filename->set(filename);
return true;
}
func save(filename. char = null) bool {
var stream void;
if filename == null {
if this.filename->empty();
return false;
stream = fopen(this.filename->ptr(), "w");
else
stream = fopen(filename, "w");
}
if stream == null;
return false;
forvar index size_t = 0, count size_t = this.items->count(); index < count; index++ {
var item. item = this.items->at(index);
if item.cover {
fprintf("%s = %c%s%c\n",
item.name->ptr(),
item.cover,
item.value->ptr(),
item.cover);
else
fprintf("%s = %s\n",
item.name->ptr(),
item.value->ptr());
}
}
fclose(stream);
}
func find(name. char) .item {
var count size_t = this.items->count();
while count {
var item. item = this.items->at(--count);
if !strcasecmp(item.name->ptr(), name) {
return item;
}
}
return null;
}
func get(name. char) .char {
var item. item = this->find(name);
if item == null;
return null;
return item.value->ptr();
}
func set(name. char, value. char) bool {
var item. item = this->find(name);
if item == null;
return false;
item.value->set(value);
return true;
}
func add(name. char, value. char = null, cover char = '"') bool {
var item. item = this->find(name);
if item ~= null;
return false;
item = this.items->new();
item.name->set(name);
if value ~= null;
item.value->set(value);
item.cover = cover;
return true;
}
}

View File

@@ -1,232 +0,0 @@
class database+ {
private import lib::sqlite3;
struct database {
db void;
}
func constructor() {
this.db = null;
}
func destructor() {
this->close();
}
func open(filename+ char, flags int =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE) bool {
this->close();
return sqlite3_open_v2(filename, &this.db, flags, null) == SQLITE_OK;
}
func close() {
if this.db ~= null;
sqlite3_close_v2(this.db), this.db = null;
}
inline exec(sql+ char) bool {
return sqlite3_exec(this.db, sql, null, null, null) == SQLITE_OK;
}
func execf(sql+ char, ...) bool {
if (sql = sqlite3_vmprintf(sql, va_start(this))) == null;
return false;
func = this->exec(sql);
sqlite3_free(sql);
}
inline prepare(stmt. stmt, sql+ char) bool {
return sqlite3_prepare_v2(this.db, sql, -1, &stmt.obj, null) == SQLITE_OK;
}
func preparef(stmt. stmt, sql+ char, ...) bool {
if (sql = sqlite3_vmprintf(sql, va_start(this))) == null;
return false;
func = this->prepare(stmt, sql);
sqlite3_free(sql);
}
func prepare_step(stmt. stmt, sql+ char) bool {
if !this->prepare(stmt, sql);
return false;
return stmt->step();
}
func preparef_step(stmt. stmt, sql+ char, ...) bool {
if (sql = sqlite3_vmprintf(sql, va_start(this))) == null;
return false;
defer sqlite3_free(sql);
if !this->prepare(stmt, sql);
return false;
return stmt->step();
}
inline last_insert_rowid() int64 {
return sqlite3_last_insert_rowid(this.db);
}
//
static inline free(ptr void) {
sqlite3_free(ptr);
}
}
class database+, stmt {
private import lib::sqlite3;
struct stmt {
obj void;
step_error bool;
}
func constructor() {
this.obj = null;
this.step_error = false;
}
func destructor() {
this->finalize();
}
inline bind_blob(index int, blob void, blob_size int, callback void) bool {
return sqlite3_bind_blob(this.obj, index, blob, blob_size, callback) == SQLITE_OK;
}
inline bind_double(index int, data double) bool {
return sqlite3_bind_double(this.obj, index, data) == SQLITE_OK;
}
inline bind_int(index int, data int) bool {
return sqlite3_bind_int(this.obj, index, data) == SQLITE_OK;
}
inline bind_null(index int) bool {
return sqlite3_bind_null(this.obj, index) == SQLITE_OK;
}
inline bind_text(index int, text+ char, text_len int, callback void) bool {
return sqlite3_bind_text(this.obj, index, text, text_len, callback) == SQLITE_OK;
}
inline bind_text16(index int, text void, text_len int, callback void) bool {
return sqlite3_bind_text16(this.obj, index, text, text_len, callback) == SQLITE_OK;
}
inline bind_text64(index int, text+ char, text_len int64, callback void, encoding char) bool {
return sqlite3_bind_text64(this.obj, index, text, text_len, callback, encoding) == SQLITE_OK;
}
inline bind_value(index int, value void) bool {
return sqlite3_bind_value(this.obj, index, value) == SQLITE_OK;
}
inline bind_zeroblob(index int, size int) bool {
return sqlite3_bind_zeroblob(this.obj, index, size) == SQLITE_OK;
}
inline bind_param_count() int {
return sqlite3_bind_parameter_count(this.obj);
}
inline bind_param_name(index int) +char {
return sqlite3_bind_parameter_name(this.obj, index);
}
inline bind_param_index(name+ char) int {
return sqlite3_bind_parameter_index(this.obj, name);
}
inline clear_bind() bool {
return sqlite3_clear_bindings(this.obj) == SQLITE_OK;
}
inline data_count() int {
return sqlite3_data_count(this.obj);
}
inline column_count() int {
return sqlite3_column_count(this.obj);
}
inline column_name(index int) +char {
return sqlite3_column_name(this.obj, index);
}
inline column_name16(index int) void {
return sqlite3_column_name16(this.obj, index);
}
func step() bool {
var result int = sqlite3_step(this.obj);
if result ~= SQLITE_ROW {
/*
SQLITE_BUSY
SQLITE_ERROR
SQLITE_MISUSE
*/
this.step_error = result ~= SQLITE_DONE;
return false;
}
return true;
}
inline step_error?() bool {
return this.step_error;
}
inline reset() bool {
return sqlite3_reset(this.obj) == SQLITE_OK;
}
inline column_blob(col int) void {
return sqlite3_column_blob(this.obj, col);
}
inline column_double(col int) double {
return sqlite3_column_double(this.obj, col);
}
inline column_int(col int) int {
return sqlite3_column_int(this.obj, col);
}
inline column_text(col int) +char {
return sqlite3_column_text(this.obj, col);
}
inline column_text16(col int) void {
return sqlite3_column_text16(this.obj, col);
}
inline column_value(col int) void {
return sqlite3_column_value(this.obj, col);
}
inline column_bytes(col int) int {
return sqlite3_column_bytes(this.obj, col);
}
inline column_bytes16(col int) int {
return sqlite3_column_bytes16(this.obj, col);
}
inline column_type(col int) int {
return sqlite3_column_type(this.obj, col);
}
func finalize() bool {
if this.obj ~= null {
if sqlite3_finalize(this.obj) ~= SQLITE_OK;
return false;
this.obj = null;
}
return true;
}
}

View File

@@ -1,117 +0,0 @@
func exec(file. char, ap void) bool {
import rt::c;
var pid pid_t = fork();
if pid == -1 {
return false;
elseif pid == 0;
execvp(file, ap);
return false;
else
wait(null);
/*
for some reasons.
*/
sleep(1);
}
return true;
}
func exec2(cmd. char) bool {
import rt::c;
alias
dmem = std::dmem,
strings = std::strings;
var args dmem;
var strs strings;
enum {
mode_none,
mode_word,
mode_quote,
mode_double_quote
}
var mode int = mode_none;
var begin size_t;
forvar index size_t = 0, count size_t = strlen(cmd); index < count; index++ {
var c char = cmd[index];
if c == ' ' or c == '\t' {
if mode == mode_word {
.args->alloc_t<char*>() =
strs->add(cmd + begin, index - begin);
mode = mode_none;
}
elseif c == '\'';
if mode == mode_none {
begin = index + 1;
mode = mode_quote;
elseif mode == mode_word;
// fixme
return false;
elseif mode == mode_quote;
.args->alloc_t<char*>() =
strs->add(cmd + begin, index - begin);
mode = mode_none;
}
elseif c == '\"';
if mode == mode_none {
begin = index + 1;
mode = mode_double_quote;
elseif mode == mode_word;
// fixme
return false;
elseif mode == mode_double_quote;
.args->alloc_t<char*>() =
strs->add(cmd + begin, index - begin);
mode = mode_none;
}
else
if mode == mode_none {
begin = index;
mode = mode_word;
}
}
}
if mode == mode_word {
.args->alloc_t<char*>() =
strs->add(cmd + begin);
}
if strs->empty() {
return false;
}
.args->alloc_t<char*>() = null;
return exec(strs->first_item(), args.ptr);
}
/*
fixme
*/
func exec3(window. game::window, text. char, cmd. char) bool {
import lib::sdl2, game;
define {
PADDING = 10;
}
var render void = window->get_render();
var font texture;
font->init(global::uni_font->create_tex(render, text, 0xff000000));
var width int = font->get_width();
var height int = font->get_height();
var rect SDL_Rect = 0;
window->get_size(&rect.w, &rect.h);
var sub_rect SDL_Rect;
sub_rect.x = (rect.w - width) / 2 - PADDING;
sub_rect.y = (rect.h - height) / 2 - PADDING;
sub_rect.w = width + (PADDING * 2);
sub_rect.h = height + (PADDING * 2);
var screen texture;
screen->init(window->screen_capture2());
screen->draw(render, 0, 0);
SDL_SetRenderDrawColor(render, 0xff, 0xff, 0xff, 0xff);
SDL_RenderFillRect(render, &sub_rect);
SDL_SetRenderDrawColor(render, 127, 127, 127, 0xff);
SDL_RenderDrawRect(render, &sub_rect);
font->draw(render,
sub_rect.x + PADDING,
sub_rect.y + PADDING);
window->present();
return exec2(cmd);
}

View File

@@ -1,12 +0,0 @@
func append_log(format. char, ...) {
import rt::c;
define {
filename = "bean.log";
}
var stream void = fopen(filename, "a");
if stream ~= null {
vfprintf(stream, format, va_start(format));
fclose(stream);
}
}

View File

@@ -1,43 +0,0 @@
/*
slow
*/
func find_pid_by_cmdline(cmdline. char) int {
import rt::c;
alias string = std::string,
strings = std::strings;
var dir void = opendir("/proc");
defer closedir(dir);
using ent. struct_dirent {
while (ent = readdir(dir)) ~= null {
if ent.d_type == DT_DIR {
if ent.d_name[0] == '.' and !ent.d_name[1] or
ent.d_name[1] == '.' and !ent.d_name[2] {
continue;
}
if isnumeric(&ent.d_name) {
lambda pread(cmd. char, lines. strings) bool [
var stream void = popen(cmd, "r");
if stream == null;
return false;
defer fclose(stream);
var line(0x200) char;
while fgets(&line, 0x200, stream) ~= null;
lines->add(&line);
return true;
];
static cmd string;
static lines strings;
lines->clear();
if pread(cmd->format("sudo cat /proc/%s/cmdline", &ent.d_name), &lines) {
if !lines->empty() {
if !strcmp(lines->first_item(), cmdline);
return atoi(&ent.d_name);
}
}
}
}
}
}
return -1;
}

View File

@@ -1,411 +0,0 @@
class wifi+ {
private import rt::c, lib::dbus;
struct wifi {
conn void;
err DBusError;
wicd wicd;
wicd_wl wicd_wl;
}
func constructor() {
this.conn = null;
dbus_error_init(&this.err);
}
func destructor() {
dbus_error_free(&this.err);
}
func init() bool {
this.conn = dbus_bus_get(DBUS_BUS_SYSTEM, &this.err);
if dbus_error_is_set(&this.err);
return false;
this.wicd->init(this.conn);
this.wicd_wl->init(this.conn);
return true;
}
//
func get_signal_strength() int {
var iwconfig. char = null;
if this.wicd->needs_external_calls() {
if (iwconfig = this.wicd_wl->get_iwconfig()) == null;
return -1;
iwconfig = strdup(iwconfig);
}
if this.wicd->get_signal_disply_type() == 0 {
func = this.wicd_wl->get_cur_signal_strength(iwconfig);
else
func = this.wicd_wl->get_cur_dbm_strength(iwconfig);
}
if iwconfig ~= null;
free(iwconfig);
}
func is_connecting() bool {
return this.wicd_wl->check_if_wireless_connecting();
}
func is_connected(signal_strength. int = null) bool {
if this.wicd_wl->check_if_wireless_connecting();
return false;
var x int = this->get_signal_strength();
if x == -1;
return false;
if signal_strength ~= null;
.signal_strength = x;
return true;
}
func scan(sync bool = false) {
this.wicd_wl->scan(sync);
}
func connect(id int) {
this.wicd_wl->connect(id);
}
//
inline get_sys_bus() void {
return this.conn;
}
inline get_bus_err() .DBusError {
return &this.err;
}
}
class wifi+, signal_thread {
private import rt::c, lib::dbus;
private alias
string = std::string,
vector = std::vector;
struct hook {
iface. char;
sig_name. char;
callback void;
arg void;
}
struct signal_thread {
thread pthread_t;
wifi. wifi;
hooks vector<hook>;
}
func constructor() {
this.thread = null;
this.wifi = null;
constructor(this);
}
func destructor() {
this->stop();
destructor(this);
}
func init(wifi. wifi) {
this.wifi = wifi;
}
/*
callback = lambda(arg void, iter void) [
...
];
*/
func hook_signal(iface. char, sig_name. char, callback void, arg void) bool {
if this.thread ~= null;
return false;
var conn void = this.wifi->get_sys_bus();
var err void = this.wifi->get_bus_err();
using rule string;
dbus_bus_add_match(conn,
rule->format("type='signal',interface='%s'", iface), err);
dbus_connection_flush(conn);
if dbus_error_is_set(err);
return false;
var hook. hook = this.hooks->new();
hook.iface = iface;
hook.sig_name = sig_name;
hook.callback = callback;
hook.arg = arg;
return true;
}
func start() bool {
if this.thread ~= null;
return true;
if pthread_create(&this.thread, null, lambda(this.signal_thread) void [
var conn void = this.wifi->get_sys_bus();
while this.thread ~= null {
for ;; {
dbus_connection_read_write(conn, 0);
var msg void = dbus_connection_pop_message(conn);
if msg == null;
break;
forvar index size_t = 0, count size_t = this.hooks->count(); index < count; index++ {
var hook. hook = this.hooks->at(index);
if dbus_message_is_signal(msg, hook.iface, hook.sig_name) {
var iter void;
if !dbus_message_iter_init(msg, &iter);
iter = null;
proto fn(arg void, iter void);
fn[hook.callback](hook.arg, iter);
break;
}
}
dbus_message_unref(msg);
}
sleep(1);
}
], this));
return false;
return true;
}
func stop() {
var thread pthread_t = this.thread;
if thread ~= null {
this.thread = null;
pthread_join(thread, null);
}
}
}
class wifi+, dbus {
private import lib::dbus;
struct dbus {
conn void;
bus_name. char;
path. char;
iface. char;
}
func init(conn void, bus_name. char, path. char, iface. char) {
this.conn = conn;
this.bus_name = bus_name;
this.path = path;
this.iface = iface;
}
func call(method. char, format. char = null, ...) void {
var msg void = dbus_message_new_method_call(this.bus_name, this.path, this.iface, method);
if msg == null;
return null;
defer dbus_message_unref(msg);
if format ~= null {
var args DBusMessageIter;
dbus_message_iter_init_append(msg, &args);
forvar ap void = va_start(this) ;; {
var type char = .format++;
if !type;
break;
if !dbus_message_iter_append_basic(&args, type, ap);
return null;
va_next<word>(ap);
}
}
if !dbus_connection_send_with_reply(this.conn, msg, &func, -1);
return null;
if func ~= null;
dbus_connection_flush(this.conn);
}
static func get(pending void, format. char = null, ...) bool {
if pending == null;
return false;
dbus_pending_call_block(pending);
var msg void = dbus_pending_call_steal_reply(pending);
dbus_pending_call_unref(pending);
if msg == null;
return false;
defer dbus_message_unref(msg);
if format ~= null {
var args DBusMessageIter;
if dbus_message_iter_init(msg, &args) {
forvar ap. void = va_start(pending) ;; {
var type char = .format++;
if !type;
break;
if dbus_message_iter_get_arg_type(&args) ~= type;
return false;
dbus_message_iter_get_basic(&args, .ap);
if !dbus_message_iter_next(&args);
break;
va_next<void>(ap);
}
}
}
return true;
}
}
class wifi+, wicd {
private import lib::dbus;
struct wicd {
bus dbus;
}
func init(conn void) {
this.bus->init(conn,
"org.wicd.daemon", "/org/wicd/daemon",
"org.wicd.daemon");
}
func format_signal_for_printing(signal int) .char {
func = null;
this.bus->get(
this.bus->call("FormatSignalForPrinting", "i", signal), "s", &func);
}
func get_signal_disply_type() int {
func = -1;
this.bus->get(
this.bus->call("GetSignalDisplayType"), "i", &func);
}
func needs_external_calls() dbus_bool_t {
func = 0;
this.bus->get(
this.bus->call("NeedsExternalCalls"), "b", &func);
}
}
class wifi+, wicd_wl {
private import lib::dbus;
struct wicd_wl {
bus dbus;
}
func init(conn void) {
this.bus->init(conn,
"org.wicd.daemon", "/org/wicd/daemon/wireless",
"org.wicd.daemon.wireless");
}
func check_if_wireless_connecting() dbus_bool_t {
func = 0;
this.bus->get(
this.bus->call("CheckIfWirelessConnecting"), "b", &func);
}
func check_wireless_connecting_msg() .char {
func = null;
this.bus->get(
this.bus->call("CheckWirelessConnectingMessage"), "s", &func);
}
// result?
func connect(id int) {
this.bus->get(
this.bus->call("ConnectWireless", "i", id));
}
func get_cur_dbm_strength(iwconfig. char) int {
func = -1;
var pending void;
if iwconfig == null {
pending = this.bus->call("GetCurrentDBMStrength");
else
pending = this.bus->call("GetCurrentDBMStrength", "s", iwconfig);
}
this.bus->get(pending, "i", &func);
}
func get_cur_signal_strength(iwconfig. char) int {
func = -1;
var pending void;
if iwconfig == null {
pending = this.bus->call("GetCurrentSignalStrength");
else
pending = this.bus->call("GetCurrentSignalStrength", "s", iwconfig);
}
this.bus->get(pending, "i", &func);
}
func get_cur_network(iwconfig. char) .char {
func = null;
var pending void;
if iwconfig == null {
pending = this.bus->call("GetCurrentNetwork");
else
pending = this.bus->call("GetCurrentNetwork", "s", iwconfig);
}
this.bus->get(pending, "s", &func);
}
func get_cur_network_id(iwconfig. char) int {
func = -1;
var pending void;
if iwconfig == null {
pending = this.bus->call("GetCurrentNetworkID");
else
pending = this.bus->call("GetCurrentNetworkID", "s", iwconfig);
}
this.bus->get(pending, "i", &func);
}
func get_iwconfig() .char {
func = null;
this.bus->get(
this.bus->call("GetIwconfig"), "s", &func);
}
func get_num_of_networks() int {
func = -1;
this.bus->get(
this.bus->call("GetNumberOfNetworks"), "i", &func);
}
func get_wireless_ip(s. char) .char {
func = null;
var pending void;
if s == null {
pending = this.bus->call("GetWirelessIP");
else
pending = this.bus->call("GetWirelessIP", "s", s);
}
this.bus->get(pending, "s", &func);
}
func get_wireless_prop(id int, prop_name. char) .char {
func = null;
this.bus->get(
this.bus->call("GetWirelessProperty", "is", id, prop_name), "s", &func);
}
// result?
func scan(sync dbus_bool_t) {
this.bus->get(
this.bus->call("Scan", "b", sync));
}
func set_wireless_prop_str(id int, prop_name. char, s. char) bool {
return this.bus->get(
this.bus->call("SetWirelessProperty", "iss", id, prop_name, s));
}
func set_wireless_prop_int(id int, prop_name. char, i int) bool {
return this.bus->get(
this.bus->call("SetWirelessProperty", "isi", id, prop_name, i));
}
}