Vesmir
Vesmir is an artificial universe simulation. It generates a galaxy and about thousand stars in it. Some stars have planets to form solar systems, where some planets has moons as their companions. All the stars and planet images are modeled in realtime based on their chemical composition, so the outlook of those objects are quite close how they would look in reality.
Vesmir demonstrates drawing operations, menues, some of the widgets how they interact with window, and how to bind own C functions to Ano script. Vesmir is not by any means a real space simulator, it is just an example, it should not be taken too serious.
User interface
Move the mouse over the galaxy and press <enter> on some star. View changes to that star, and if star has planets you can see some squares rounding around a cross. Squares indicates planets and cross is the star at the center of the solarsystem. Move mouse over one of the planets, press <enter> again and view changes to planet view. Backspace key navigates back to previous view. Galaxy and solar systems can be zoomed with mouse wheel (or buttons 4 and 5 to be exact), and they can be moved around by pressing mouse button 1 (that's usually the left mouse button) while moving the mouse.
In galaxy there is black holes (hard to find, but one sits exactly at the center of the galaxy), neutron stars, ordinary stars like the Sun, terrestrial planets with atmosphere like Mars, and gas giants like Saturn. Try to find another Earth! Stars also simulates nuclear fusion, so after considerably amount of time you may see a message saying some star has collapsed to neutron star or black hole. Roll the Time warp to southeast and wait.
Star and planet details can be viewed by pressing Print object button. Details are printed to standard output. Star and planet images can be saved to disk by pressing Save object button. Render object button opens star or planet image in separate window.
View reset button resets the view to its default position and sets zooming to zero. Time reset button resets the time warp setting, making clock to run at normal speed.
Compilation
Easiest way to get Vesmir running is to go to examples directory in package root, and run:
$ ./build.sh gui_vesmir
build.sh script compiles Ano script, widget definitions and menu tables to C, copies source files in place and pops up instructions what to do next. Follow them. Check also examples/README for more info.
Screenshots
Preview
;
; @ANO_SCRIPT_NAME gui_vesmir
; @ANO_SCRIPT_VERSION 0.0.3
; @ANO_SCRIPT_DESCRIPTION Artificial universe simulation
;
; List of files to unveil if unveil() support is in use:
;
; @ANO_UNVEIL_FILES "examples/datafiles/vesmir_appicon.tga = r", \
; "share/detroit/fonts/NotoSans-Italic.ttf = r", \
; "share/detroit/fonts/NotoSans-Regular.ttf = r", \
; "/tmp = rw"
;
; @ANO_FLAGS_VAR_NAME_SUBS [x]
; @ANO_FLAGS_VAR_WARN_UNUSED [ ]
;
; Copyright (c) 2016-2023, Jani Salonen <salojan at goto10 piste co>
; All rights reserved.
;
; Global uninitialized variables
var [handle] hnd_win_main
var [handle] hnd_win_view
var [handle] hnd_win_preview
var [handle] hnd_fnt_title
var [handle] hnd_fnt_view
var [handle] hnd_fnt_selected
var [handle] hnd_fnt_selection
; Global variables
mov img_dir ("/tmp")
mov hlp_txt ("LMB + mouse to move view, wheel to zoom, enter to select, backspace to previous view")
mov hlp_clr (# 0xff, 0xff, 0xff, 0x00)
mov fnt ("share/detroit/fonts/NotoSans-Regular.ttf")
mov fnt_clr (# 0xff, 0xd7, 0x69, 0x00)
mov fnt_sz_big ([uint] 14)
mov fnt_sz_med ([uint] 10)
mov fnt_sz_sml ([uint] 8)
mov view (0)
mov xpos (0)
mov ypos (0)
mov xpre (0)
mov ypre (0)
mov zoom_min (0)
mov zoom_max (100)
mov zoom_slc (10)
mov zoom (zoom_min)
mov galaxy ([ulong] 0)
mov star ([ulong] 0)
mov planet ([ulong] 0)
mov moon ([ulong] 0)
mov mess ([uint] 1)
; Initialize windowing system
window_init
; Open main window
window_open ("Vesmir", NULL, \
[handle] @0, [uint] 1, [uint] 0, [uint] 0, \
[int] -1, [int] -1, [uint] 800, [uint] 600, \
NULL, NULL, NULL, NULL, NULL, NULL, \
NULL, NULL, "cb_destroy_main", \
NULL, NULL, NULL, "cb_open_main")
end
;
; Main window callbacks
;
callback cb_open_main (_hnd) {
mov hnd_win_main (_hnd)
; Set window icon
window_icon (hnd_win_main, \
"examples/datafiles/vesmir_appicon.tga")
; Open drawing window
window_open (NULL, NULL, \
hnd_win_main, [uint] 0, [uint] 0, [uint] 1, \
[int] 20, [int] 180, [uint] 760, [uint] 400, \
"cb_mainloop_draw", NULL, \
"cb_keypress_draw", "cb_keyrelease_draw", \
"cb_buttonpress_draw", "cb_buttonrelease_draw", \
NULL, NULL, NULL, \
"cb_motion_draw", NULL, NULL, "cb_open_draw")
; Open fonts
font_open (fnt, fnt_sz_big, [uint] 0)
cmp rc (INVALID)
je "cb_open_main_end"
mov hnd_fnt_title (rc)
font_open (fnt, fnt_sz_big, [uint] 0)
cmp rc (INVALID)
je "cb_open_main_end"
mov hnd_fnt_view (rc)
font_open (fnt, fnt_sz_med, [uint] 0)
cmp rc (INVALID)
je "cb_open_main_end"
mov hnd_fnt_selected (rc)
font_open (fnt, fnt_sz_med, [uint] 0)
cmp rc (INVALID)
je "cb_open_main_end"
mov hnd_fnt_selection (rc)
font_open (fnt, fnt_sz_sml, [uint] 0)
cmp rc (INVALID)
je "cb_open_main_end"
mov hnd_fnt_date (rc)
; Pre-render some static strings to be displayed later
font_render (hnd_fnt_selected, "UTF-8", "Selected:", \
[uint] 0, fnt_clr)
font_render (hnd_fnt_view, "UTF-8", "View:", \
[uint] 0, fnt_clr)
; Map main window
window_map (hnd_win_main)
: "cb_open_main_end"
}
callback cb_destroy_main {
window_close (hnd_win_main)
font_close (hnd_fnt_title)
font_close (hnd_fnt_view)
font_close (hnd_fnt_selected)
font_close (hnd_fnt_selection)
font_close (hnd_fnt_date)
exit
}
;
; Drawing window callbacks
;
callback cb_mainloop_draw {
draw_wipe (hnd_win_view)
cmp view (0)
je "cb_mainloop_draw_galaxy"
cmp view (1)
je "cb_mainloop_draw_star"
cmp view (2)
je "cb_mainloop_draw_planet"
end
: "cb_mainloop_draw_galaxy"
; Main loop for galaxy view
mov galaxy_x (xpos)
mov galaxy_y (ypos)
mov galaxy_z (zoom)
galaxy_live (hnd_win_view, galaxy, \
galaxy_x, galaxy_y, galaxy_z)
galaxy_get_name (galaxy)
mov _name (rc)
call "cb_mainloop_draw_texts" (_name)
jmp "cb_mainloop_draw_done"
: "cb_mainloop_draw_star"
; Main loop for star view
mov star_x (xpos)
mov star_y (ypos)
mov star_z (zoom)
star_live (hnd_win_view, galaxy, star, \
star_x, star_y, star_z)
star_get_name (galaxy, star)
mov _name (rc)
call "cb_mainloop_draw_texts" (_name)
jmp "cb_mainloop_draw_done"
: "cb_mainloop_draw_planet"
; Main loop for planet view
mov planet_x (xpos)
mov planet_y (ypos)
mov planet_z (zoom)
planet_live (hnd_win_view, galaxy, star, planet, \
planet_x, planet_y, planet_z)
planet_get_name (galaxy, star, planet)
mov _name (rc)
call "cb_mainloop_draw_texts" (_name)
jmp "cb_mainloop_draw_done"
: "cb_mainloop_draw_done"
; Zoom view slowly back to its base position
cmp zoom (zoom_min)
jbe "cb_mainloop_draw_end"
sub zoom (0.0005)
: "cb_mainloop_draw_end"
}
function cb_mainloop_draw_texts (_object) {
universe_chk_message
cmp mess (rc)
je "cb_mainloop_draw_texts_ok"
mov mess (rc)
universe_get_message
mov _mess (rc)
widget_update_label (hnd_win_main, "help", \
_mess, NULL, fnt, 0, 0, 0, hlp_clr)
widget_refresh (hnd_win_main)
: "cb_mainloop_draw_texts_ok"
universe_get_date
mov _date (rc)
font_render (hnd_fnt_date, "UTF-8", _date, [uint] 0, fnt_clr)
font_render (hnd_fnt_title, "UTF-8", _object, [uint] 0, fnt_clr)
font_get_width (hnd_fnt_date)
mov _w (rc)
font_get_height (hnd_fnt_date)
mov _h (rc)
draw_text (hnd_win_view, hnd_fnt_title, \
[int] 80, [int] 80)
draw_text (hnd_win_view, hnd_fnt_view, \
[int] 20, [int] 80)
draw_text (hnd_win_view, hnd_fnt_selected, \
[int] 20, [int] 120)
draw_text (hnd_win_view, hnd_fnt_selection, \
[int] 80, [int] 120)
draw_text (hnd_win_view, hnd_fnt_date, \
[int] 760 - _w, [int] 400 - _h)
}
callback cb_keypress_draw (x, y, _x_root, _y_root, _state, _keycode, _key) {
cmp _keycode (6)
je "cb_keypress_draw_enter"
cmp _keycode (2)
je "cb_keypress_draw_backspace"
end
: "cb_keypress_draw_enter"
cmp view (0)
je "cb_keypress_draw_enter_galaxy"
cmp view (1)
je "cb_keypress_draw_enter_star"
end
: "cb_keypress_draw_enter_galaxy"
; Switch from galaxy to star view
call "cb_keypress_draw_enter_switch" (1)
end
: "cb_keypress_draw_enter_star"
; Switch from star to planet view
call "cb_keypress_draw_enter_switch" (2)
end
: "cb_keypress_draw_backspace"
cmp view (1)
je "cb_keypress_draw_backspace_star"
cmp view (2)
je "cb_keypress_draw_backspace_planet"
end
: "cb_keypress_draw_backspace_star"
; Switch from star to galaxy view
call "cb_keypress_draw_backspace_switch" \
(galaxy_x, galaxy_y, galaxy_z, 0)
end
: "cb_keypress_draw_backspace_planet"
; Switch from planet to star view
call "cb_keypress_draw_backspace_switch" \
(star_x, star_y, star_z, 1)
}
function cb_keypress_draw_enter_switch (_switch) {
mov xpos (0)
mov ypos (0)
mov xpre (0)
mov ypre (0)
mov zoom (zoom_min)
mov view (_switch)
widget_update_label (hnd_win_main, "help", \
hlp_txt, NULL, fnt, 0, 0, 0, hlp_clr)
widget_refresh (hnd_win_main)
}
function cb_keypress_draw_backspace_switch (_switch_x, _switch_y, _switch_z, _switch) {
mov xpos (_switch_x)
mov ypos (_switch_y)
mov zoom (_switch_z)
mov view (_switch)
widget_update_label (hnd_win_main, "help", \
hlp_txt, NULL, fnt, 0, 0, 0, hlp_clr)
widget_refresh (hnd_win_main)
}
callback cb_keyrelease_draw (x, y, _x_root, _y_root, _state, _keycode, _key) {
}
callback cb_buttonpress_draw (x, y, _x_root, _y_root, _state, _button) {
cmp _button (1)
je "cb_buttonpress_draw_zoom_in"
cmp _button (5)
je "cb_buttonpress_draw_zoom_in"
cmp _button (3)
je "cb_buttonpress_draw_zoom_out"
cmp _button (4)
je "cb_buttonpress_draw_zoom_out"
; Clear previous pointer position for motion event
mov xpre (0)
mov ypre (0)
end
: "cb_buttonpress_draw_zoom_in"
; Zoom view inwards
cmp zoom (zoom_max)
jae "cb_buttonpress_draw_zoom_in_end"
mov _i (zoom_max)
sub _i (zoom)
div _i (zoom_slc)
add zoom (_i)
: "cb_buttonpress_draw_zoom_in_end"
end
: "cb_buttonpress_draw_zoom_out"
; Zoom view outwards
cmp zoom (zoom_min)
jbe "cb_buttonpress_draw_zoom_out_end"
mov _o (zoom_max)
sub _o (zoom)
div _o (zoom_slc)
sub zoom (_o)
: "cb_buttonpress_draw_zoom_out_end"
}
callback cb_buttonrelease_draw (x, y, _x_root, _y_root, _state, _button) {
}
callback cb_motion_draw (x, y, _x_root, _y_root, _state, _detail) {
; 256 = Button1Mask, 1 << 8
cmp _state (256)
jne "cb_motion_draw_view"
; Button 1 pressed with mouse motion, move view
cmp xpre (0)
jne "cb_motion_draw_a"
mov xpre (x)
: "cb_motion_draw_a"
cmp ypre (0)
jne "cb_motion_draw_b"
mov ypre (y)
: "cb_motion_draw_b"
mov _x (x)
mov _y (y)
sub _x (xpre)
sub _y (ypre)
mul _x (1.5)
mul _y (1.5)
add xpos (_x)
add ypos (_y)
mov xpre (x)
mov ypre (y)
end
: "cb_motion_draw_view"
; Select object closest to mouse pointer
cmp view (0)
je "cb_motion_draw_view_galaxy"
cmp view (1)
je "cb_motion_draw_view_star"
cmp view (2)
je "cb_motion_draw_view_planet"
end
: "cb_motion_draw_view_galaxy"
; Get the closest star
galaxy_live_closest (galaxy, x, y)
cmp rc (0)
je "cb_motion_draw_view_galaxy_end"
mov star (rc)
dec star
; Get the closest star name and render it
star_get_name (galaxy, star)
mov _name (rc)
font_render (hnd_fnt_selection, "UTF-8", _name, [uint] 0, fnt_clr)
: "cb_motion_draw_view_galaxy_end"
end
: "cb_motion_draw_view_star"
; Get the closest planet
star_live_closest (galaxy, star, x, y)
cmp rc (0)
je "cb_motion_draw_view_star_end"
mov planet (rc)
dec planet
; Get the closest planet name and render it
planet_get_name (galaxy, star, planet)
mov _name (rc)
font_render (hnd_fnt_selection, "UTF-8", _name, [uint] 0, fnt_clr)
: "cb_motion_draw_view_star_end"
end
: "cb_motion_draw_view_planet"
; Get the closest moon
planet_live_closest (galaxy, star, planet, x, y)
cmp rc (0)
je "cb_motion_draw_view_planet_end"
mov moon (rc)
dec moon
; Get the closest moon name and render it
satellite_get_name (galaxy, star, planet, moon)
mov _name (rc)
font_render (hnd_fnt_selection, "UTF-8", _name, [uint] 0, fnt_clr)
: "cb_motion_draw_view_planet_end"
}
callback cb_open_draw (_hnd) {
mov hnd_win_view (_hnd)
; Map drawing window
window_map (hnd_win_view)
}
;
; Preview window callbacks
;
callback cb_open_preview (_hnd) {
mov hnd_win_preview (_hnd)
cmp view (1)
jne "cb_open_preview_planet"
star_render (hnd_win_preview, galaxy, star)
jmp "cb_open_preview_end"
: "cb_open_preview_planet"
cmp view (2)
jne "cb_open_preview_end"
planet_render (hnd_win_preview, galaxy, star, planet)
jmp "cb_open_preview_end"
: "cb_open_preview_end"
; Map preview window
window_map (hnd_win_preview)
}
callback cb_destroy_preview {
window_close (hnd_win_preview)
mov hnd_win_preview (INVALID)
}
;
; Widget callbacks
;
callback cb_push_renderobject (_widget_name, _widget_id, _min, _max, _steps, _step) {
cmp view (0)
je "cb_push_renderobject_galaxy"
cmp view (1)
je "cb_push_renderobject_star"
cmp view (2)
je "cb_push_renderobject_planet"
end
: "cb_push_renderobject_galaxy"
universe_set_message \
("Rendering galaxy is not supported")
end
: "cb_push_renderobject_star"
; Open preview window for star
call "cb_push_renderobject_open" \
("Vesmir star preview")
end
: "cb_push_renderobject_planet"
; Open preview window for planet
call "cb_push_renderobject_open" \
("Vesmir planet preview")
}
function cb_push_renderobject_open (_title) {
cmp hnd_win_preview (INVALID)
je "cb_push_renderobject_ok"
window_close (hnd_win_preview)
: "cb_push_renderobject_ok"
window_open (_title, NULL, \
[handle] @0, [uint] 2, [uint] 0, [uint] 0, \
[int] -1, [int] -1, [uint] 256, [uint] 256, \
NULL, NULL, NULL, NULL, NULL, NULL, \
NULL, NULL, "cb_destroy_preview", \
NULL, NULL, NULL, "cb_open_preview")
}
callback cb_push_printobject (_widget_name, _widget_id, _min, _max, _steps, _step) {
cmp view (0)
je "cb_push_printobject_galaxy"
cmp view (1)
je "cb_push_printobject_star"
cmp view (2)
je "cb_push_printobject_planet"
end
: "cb_push_printobject_galaxy"
; Print galaxy details
galaxy_print (galaxy)
end
: "cb_push_printobject_star"
; Print star details
star_print (galaxy, star)
end
: "cb_push_printobject_planet"
; Print planet details
planet_print (galaxy, star, planet)
}
callback cb_push_saveobject (_widget_name, _widget_id, _min, _max, _steps, _step) {
cmp view (0)
je "cb_push_saveobject_galaxy"
cmp view (1)
je "cb_push_saveobject_star"
cmp view (2)
je "cb_push_saveobject_planet"
end
: "cb_push_saveobject_galaxy"
universe_set_message ("Saving galaxy is not supported")
end
: "cb_push_saveobject_star"
; Save star image
star_store (galaxy, star, img_dir)
end
: "cb_push_saveobject_planet"
; Save planet image
planet_store (galaxy, star, planet, img_dir)
}
callback cb_push_viewreset (_widget_name, _widget_id, _min, _max, _steps, _step) {
; Reset the view
mov xpos (0)
mov ypos (0)
mov zoom (zoom_min)
}
callback cb_push_timereset (_widget_name, _widget_id, _min, _max, _steps, _step) {
; Reset the clock
clock_set_multiplier (1)
widget_step_set (hnd_win_main, "time_warp", [uint] 1)
}
callback cb_turn_timewarp (_widget_name, _widget_id, _min, _max, _steps, _step) {
; Speed up the universe
mov _mul (((_step * _step) * _step) * _step)
clock_set_multiplier (_mul)
}
;
; Menu item callbacks
;
callback cb_file_exit (_item, _position, _tag, _flag) {
jmp "cb_destroy_main"
}
callback cb_object_render (_item, _position, _tag, _flag) {
mov _msg ("Not implemented, use widgets instead")
dump _msg
}
callback cb_object_print (_item, _position, _tag, _flag) {
mov _msg ("Not implemented, use widgets instead")
dump _msg
}
callback cb_object_save (_item, _position, _tag, _flag) {
mov _msg ("Not implemented, use widgets instead")
dump _msg
}
callback cb_time_reset (_item, _position, _tag, _flag) {
mov _msg ("Not implemented, use widgets instead")
dump _msg
}
callback cb_time_set (_item, _position, _tag, _flag) {
mov _msg ("Not implemented, use widgets instead")
dump _msg
}
;
; Copyright (c) 2016-2023, Jani Salonen <salojan at goto10 piste co>
; All rights reserved.
;
; @WIDGET_USE_BOUNDING_BOXES no
;
window "1" {
set "0" {
widget "background" {
name "background"
state enable
image "examples/datafiles/background.tga"
}
widget "label" {
name "help"
state enable
position x = 20, y = 580
label "LMB + mouse to move view, wheel to zoom, enter to select, backspace to previous view", \
charset = UTF-8, size = 8, \
color = rgb:#ffffff, \
justification = left
}
widget "pushbutton_2"
name "render_object"
state enable
type 3
position x = 40, y = 100
title "Render object", \
charset = UTF-8, size = 10, \
color = rgb:#ffffff, \
justification = center, \
position = above, x = 0, y = -10
sticky no
action push = cb_push_renderobject
}
widget "pushbutton_2" {
name "print_object"
state enable
type 3
position x = 160, y = 100
title "Print object", \
charset = UTF-8, size = 10, \
color = rgb:#ffffff, \
justification = center, \
position = above, x = 0, y = -10
sticky no
action push = cb_push_printobject
}
widget "pushbutton_2" {
name "save_object"
state enable
type 3
position x = 280, y = 100
title "Save object", \
charset = UTF-8, size = 10, \
color = rgb:#ffffff, \
justification = center, \
position = above, x = 0, y = -10
sticky no
action push = cb_push_saveobject
}
widget "pushbutton_2" {
name "view_reset"
state enable
type 1
position x = 440, y = 100
title "View reset", \
charset = UTF-8, size = 10, \
color = rgb:#ffffff, \
justification = center, \
position = above, x = 0, y = -10
sticky no
action push = cb_push_viewreset
}
widget "pushbutton_2" {
name "time_reset"
state enable
type 1
position x = 560, y = 100
title "Time reset", \
charset = UTF-8, size = 10, \
color = rgb:#ffffff, \
justification = center, \
position = above, x = 0, y = -10
sticky no
action push = cb_push_timereset
}
widget "turnswitch" {
name "time_warp"
state enable
type 1
position x = 670, y = 60
angle min = 5, max = 355
steps start = 1, total = 1000
title "Time warp", \
charset = UTF-8, size = 10, \
color = rgb:#ffffff, \
justification = center, \
position = above, x = 0, y = -5
trigger constant
action turn = cb_turn_timewarp
}
}
}
;
; Copyright (c) 2016-2023, Jani Salonen <salojan at goto10 piste co>
; All rights reserved.
;
;
; container_type "name" {
;
window "1" {
;
; menu "name" { optional_icon
;
menu "File" { examples/datafiles/vesmir_menu_1.tga
;
; type "name", id, callback_func, flags, optional_icon
;
item "Exit", 1, cb_file_exit, none, none
}
menu "Object" {
item "Render", 10, cb_object_render, none, none
item "Print", 11, cb_object_print, none, none
item "Save", 12, cb_object_save, none, none
}
menu "Time" {
item "Reset", 20, cb_time_reset, none, none
delim
radio "Increase 10%", 30, cb_time_set, none, none
radio "Increase 20%", 30, cb_time_set, none, none
radio "Increase 30%", 30, cb_time_set, none, none
radio "Increase 40%", 30, cb_time_set, none, none
radio "Increase 50%", 30, cb_time_set, none, none
radio "Increase 60%", 30, cb_time_set, none, none
radio "Increase 70%", 30, cb_time_set, none, none
radio "Increase 80%", 30, cb_time_set, none, none
radio "Increase 90%", 30, cb_time_set, none, none
radio "Increase 100%", 30, cb_time_set, none, none
}
}
Copyright © 2023, Jani Salonen <salojan at goto10 piste co>. Piste is finnish word and means dot. All rights reserved.





