2023-09-11 04:45:59 +00:00
-- Entrypoint for the app. You can edit this file from within the app if
-- you're careful.
2022-08-08 17:33:47 +00:00
2022-09-03 21:13:22 +00:00
-- files that come with LÖVE; we can't edit those from within the app
utf8 = require ' utf8 '
2022-07-23 18:48:38 +00:00
2022-09-03 21:13:22 +00:00
function load_file_from_source_or_save_directory ( filename )
local contents = love.filesystem . read ( filename )
local code , err = loadstring ( contents , filename )
if code == nil then
error ( err )
2022-06-09 15:15:32 +00:00
end
2022-09-03 21:13:22 +00:00
return code ( )
2022-07-01 05:46:45 +00:00
end
2022-09-03 21:13:22 +00:00
json = load_file_from_source_or_save_directory ( ' json.lua ' )
2022-07-30 20:36:24 +00:00
2022-09-03 21:13:22 +00:00
load_file_from_source_or_save_directory ( ' app.lua ' )
load_file_from_source_or_save_directory ( ' test.lua ' )
2022-07-30 19:53:14 +00:00
2022-09-03 21:13:22 +00:00
load_file_from_source_or_save_directory ( ' keychord.lua ' )
load_file_from_source_or_save_directory ( ' button.lua ' )
2022-06-07 20:24:43 +00:00
2022-09-03 21:13:22 +00:00
-- both sides require (different parts of) the logging framework
load_file_from_source_or_save_directory ( ' log.lua ' )
2022-06-18 23:25:20 +00:00
2022-09-05 18:28:03 +00:00
-- both sides use drawings
load_file_from_source_or_save_directory ( ' icons.lua ' )
load_file_from_source_or_save_directory ( ' drawing.lua ' )
load_file_from_source_or_save_directory ( ' geom.lua ' )
load_file_from_source_or_save_directory ( ' help.lua ' )
load_file_from_source_or_save_directory ( ' drawing_tests.lua ' )
2022-09-03 21:13:22 +00:00
-- but some files we want to only load sometimes
2023-09-08 15:22:45 +00:00
function App . load ( )
2022-09-18 03:37:40 +00:00
log_new ( ' session ' )
2023-09-08 15:22:45 +00:00
if love.filesystem . getInfo ( ' config ' ) then
Settings = json.decode ( love.filesystem . read ( ' config ' ) )
Current_app = Settings.current_app
2022-12-04 05:09:08 +00:00
end
2023-12-07 06:59:24 +00:00
-- Current_app =
-- | run
-- | source
-- | {name=warning message='...' next_app = run|source}
2022-09-03 21:13:22 +00:00
if Current_app == nil then
Current_app = ' run '
2022-07-23 18:48:38 +00:00
end
2022-08-06 16:00:00 +00:00
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
2022-10-27 06:13:22 +00:00
load_file_from_source_or_save_directory ( ' errors.lua ' )
2022-09-03 21:13:22 +00:00
load_file_from_source_or_save_directory ( ' file.lua ' )
load_file_from_source_or_save_directory ( ' run.lua ' )
2022-09-04 01:10:12 +00:00
load_file_from_source_or_save_directory ( ' commands.lua ' )
2022-09-03 21:13:22 +00:00
load_file_from_source_or_save_directory ( ' edit.lua ' )
load_file_from_source_or_save_directory ( ' text.lua ' )
load_file_from_source_or_save_directory ( ' search.lua ' )
load_file_from_source_or_save_directory ( ' select.lua ' )
load_file_from_source_or_save_directory ( ' undo.lua ' )
load_file_from_source_or_save_directory ( ' text_tests.lua ' )
load_file_from_source_or_save_directory ( ' run_tests.lua ' )
2022-11-16 07:39:01 +00:00
load_file_from_source_or_save_directory ( ' debug.lua ' )
2022-09-05 19:38:11 +00:00
elseif Current_app == ' source ' then
2022-09-03 21:13:22 +00:00
load_file_from_source_or_save_directory ( ' source_file.lua ' )
load_file_from_source_or_save_directory ( ' source.lua ' )
2022-09-04 01:10:12 +00:00
load_file_from_source_or_save_directory ( ' source_commands.lua ' )
2022-09-03 21:13:22 +00:00
load_file_from_source_or_save_directory ( ' source_edit.lua ' )
load_file_from_source_or_save_directory ( ' log_browser.lua ' )
load_file_from_source_or_save_directory ( ' source_text.lua ' )
load_file_from_source_or_save_directory ( ' search.lua ' )
2022-09-06 17:05:20 +00:00
load_file_from_source_or_save_directory ( ' source_select.lua ' )
2022-09-03 21:13:22 +00:00
load_file_from_source_or_save_directory ( ' source_undo.lua ' )
load_file_from_source_or_save_directory ( ' colorize.lua ' )
load_file_from_source_or_save_directory ( ' source_text_tests.lua ' )
load_file_from_source_or_save_directory ( ' source_tests.lua ' )
2023-12-07 06:59:24 +00:00
elseif current_app_is_warning ( ) then
2022-09-05 19:38:11 +00:00
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-28 23:51:39 +00:00
end
end
2022-09-03 21:13:22 +00:00
function App . initialize_globals ( )
2023-12-07 04:14:24 +00:00
Supported_versions = { ' 11.5 ' , ' 11.4 ' , ' 12.0 ' } -- put the recommended version first
check_love_version_for_tests ( )
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
run.initialize_globals ( )
elseif Current_app == ' source ' then
source.initialize_globals ( )
2023-12-07 06:59:24 +00:00
elseif current_app_is_warning ( ) then
2022-07-17 02:56:06 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-17 02:56:06 +00:00
end
2022-09-03 21:13:22 +00:00
-- for hysteresis in a few places
2022-11-04 04:02:31 +00:00
Current_time = 0
Last_focus_time = 0 -- https://love2d.org/forums/viewtopic.php?p=249700
Last_resize_time = 0
2023-12-07 05:32:10 +00:00
-- Another weird bit for a class of corner cases. E.g.:
-- * I press ctrl+e, switch Current_app. I don't want the new app to receive
-- text_input and key_release events.
-- If I try to avoid text_input events by switching modes on key_release, I
-- hit a new problem:
-- * I press ctrl+e, am running an untested version, Current_app goes to
2023-12-07 06:59:24 +00:00
-- 'warning', and immediately rolls back out of 'warning' in the
-- key_release event.
2023-12-07 05:32:10 +00:00
-- Skip_rest_of_key_events is ugly, but feels cleaner than creating yet
-- another possible value for Current_app.
Skip_rest_of_key_events = nil
2022-07-01 05:46:45 +00:00
end
2022-05-02 04:55:57 +00:00
2023-12-07 04:14:24 +00:00
function check_love_version_for_tests ( )
if array.find ( Supported_versions , Version ) == nil then
-- warning to include in an error message if any tests failed
Warning_before_tests = ( " This app hasn't been tested with LÖVE version %s. " ) : format ( Version )
end
2022-07-19 14:05:23 +00:00
end
2022-07-17 02:56:06 +00:00
2022-09-03 21:13:22 +00:00
function App . initialize ( arg )
2023-01-16 17:48:06 +00:00
love.keyboard . setTextInput ( true ) -- bring up keyboard on touch screen
love.keyboard . setKeyRepeat ( true )
love.graphics . setBackgroundColor ( 1 , 1 , 1 )
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
run.initialize ( arg )
elseif Current_app == ' source ' then
source.initialize ( arg )
2023-12-07 06:59:24 +00:00
elseif current_app_is_warning ( ) then
2022-07-29 04:58:46 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-29 04:58:46 +00:00
end
2023-12-07 05:32:10 +00:00
check_love_version ( )
end
function check_love_version ( )
if array.find ( Supported_versions , Version ) == nil then
2023-12-07 06:59:24 +00:00
show_warning (
( " This app hasn't been tested with LÖVE version %s; please switch to version %s if you run into issues. Press any key to continue. " ) : format ( Version , Supported_versions [ 1 ] ) )
2023-12-07 05:32:10 +00:00
-- continue initializing everything; hopefully we won't have errors during initialization
end
2022-07-29 04:58:46 +00:00
end
2022-09-03 21:13:22 +00:00
function App . resize ( w , h )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
if run.resize then run.resize ( w , h ) end
elseif Current_app == ' source ' then
if source.resize then source.resize ( w , h ) end
2022-07-17 04:10:53 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-17 02:56:06 +00:00
end
2022-11-04 04:02:31 +00:00
Last_resize_time = Current_time
2022-07-17 02:56:06 +00:00
end
2022-05-23 01:27:48 +00:00
function App . filedropped ( file )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
2022-12-24 01:16:19 +00:00
if run.file_drop then run.file_drop ( file ) end
2022-09-03 21:13:22 +00:00
elseif Current_app == ' source ' then
2022-12-24 01:16:19 +00:00
if source.file_drop then source.file_drop ( file ) end
2022-09-03 21:13:22 +00:00
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-08-11 17:07:58 +00:00
end
2022-07-17 02:56:06 +00:00
end
2022-07-25 22:33:06 +00:00
function App . focus ( in_focus )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-07-25 22:33:06 +00:00
if in_focus then
2022-11-04 04:02:31 +00:00
Last_focus_time = Current_time
2022-07-25 22:33:06 +00:00
end
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
if run.focus then run.focus ( in_focus ) end
elseif Current_app == ' source ' then
if source.focus then source.focus ( in_focus ) end
2022-07-20 22:43:01 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-19 14:05:23 +00:00
end
end
2022-05-23 01:27:48 +00:00
function App . draw ( )
2023-11-13 00:26:51 +00:00
if Current_app == ' run ' then
run.draw ( )
elseif Current_app == ' source ' then
source.draw ( )
2023-12-07 06:59:24 +00:00
elseif current_app_is_warning ( ) then
2023-10-10 03:00:36 +00:00
love.graphics . setColor ( 0 , 0 , 1 )
love.graphics . rectangle ( ' fill ' , 0 , 0 , App.screen . width , App.screen . height )
love.graphics . setColor ( 1 , 1 , 1 )
2023-12-07 06:59:24 +00:00
love.graphics . printf ( Current_app.message , 40 , 40 , 600 )
2022-07-20 22:43:01 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-08-12 02:37:00 +00:00
end
end
2022-05-23 01:27:48 +00:00
function App . update ( dt )
2022-11-04 04:02:31 +00:00
Current_time = Current_time + dt
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-07-12 20:45:38 +00:00
-- some hysteresis while resizing
2022-11-04 04:02:31 +00:00
if Current_time < Last_resize_time + 0.1 then
2022-08-12 02:37:00 +00:00
return
end
2022-09-03 21:13:22 +00:00
--
if Current_app == ' run ' then
run.update ( dt )
elseif Current_app == ' source ' then
source.update ( dt )
2022-08-12 02:37:00 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-08-12 02:37:00 +00:00
end
end
2022-12-24 01:16:19 +00:00
function App . keychord_press ( chord , key )
2022-09-03 21:13:22 +00:00
-- ignore events for some time after window in focus (mostly alt-tab)
2022-11-04 04:02:31 +00:00
if Current_time < Last_focus_time + 0.01 then
2022-08-11 17:07:58 +00:00
return
end
2022-09-03 21:13:22 +00:00
--
2023-12-07 05:32:10 +00:00
Skip_rest_of_key_events = nil
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then
2023-10-10 03:00:36 +00:00
if chord == ' C-c ' then
2023-12-07 09:08:09 +00:00
love.system . setClipboardText ( warning_message ( ) )
2023-12-07 05:32:10 +00:00
else
2023-12-07 06:59:24 +00:00
clear_warning ( )
2023-12-07 05:32:10 +00:00
Skip_rest_of_key_events = true
2023-10-10 03:00:36 +00:00
end
return
end
2022-09-04 02:00:56 +00:00
if chord == ' C-w ' then
2022-09-03 21:13:22 +00:00
-- carefully save settings
if Current_app == ' run ' then
2023-09-08 21:16:50 +00:00
if Directory_error then return end -- make sure we never ever save 'run' settings if we failed to load Directory. All bets are off. Perform no operations that might persist past restart. Debugging errors in Directory_error code will be more inconvenient, but so it goes.
2022-09-03 21:13:22 +00:00
local source_settings = Settings.source
2022-09-10 05:30:37 +00:00
Settings = run.settings ( )
2022-09-03 21:13:22 +00:00
Settings.source = source_settings
if run.quit then run.quit ( ) end
Current_app = ' source '
2023-09-04 22:07:54 +00:00
-- preserve any Error_message when going from run to source
2022-09-03 21:13:22 +00:00
elseif Current_app == ' source ' then
Settings.source = source.settings ( )
if source.quit then source.quit ( ) end
Current_app = ' run '
2023-09-04 22:07:54 +00:00
Error_message = nil
2023-12-07 06:59:24 +00:00
elseif current_app_is_warning ( ) then
2022-07-29 04:58:46 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
end
Settings.current_app = Current_app
love.filesystem . write ( ' config ' , json.encode ( Settings ) )
-- reboot
load_file_from_source_or_save_directory ( ' main.lua ' )
App.undo_initialize ( )
App.run_tests_and_initialize ( )
2023-12-07 05:32:10 +00:00
Skip_rest_of_key_events = true
2022-08-04 04:08:25 +00:00
return
end
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
2022-12-24 01:16:19 +00:00
if run.keychord_press then run.keychord_press ( chord , key ) end
2022-09-03 21:13:22 +00:00
elseif Current_app == ' source ' then
2022-12-24 01:16:19 +00:00
if source.keychord_press then source.keychord_press ( chord , key ) end
2022-08-04 04:08:25 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-08-04 04:08:25 +00:00
end
end
2022-05-23 01:27:48 +00:00
function App . textinput ( t )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-09-03 21:13:22 +00:00
-- ignore events for some time after window in focus (mostly alt-tab)
2022-11-04 04:02:31 +00:00
if Current_time < Last_focus_time + 0.01 then
2022-08-04 04:08:25 +00:00
return
end
2022-09-03 21:13:22 +00:00
--
2023-12-07 05:32:10 +00:00
if Skip_rest_of_key_events then return end
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
2022-12-24 01:16:19 +00:00
if run.text_input then run.text_input ( t ) end
2022-09-03 21:13:22 +00:00
elseif Current_app == ' source ' then
2022-12-24 01:16:19 +00:00
if source.text_input then source.text_input ( t ) end
2022-07-22 18:13:39 +00:00
else
2022-09-03 21:13:22 +00:00
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-19 14:05:23 +00:00
end
end
2022-12-10 19:28:34 +00:00
function App . keyreleased ( key , scancode )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-09-03 21:13:22 +00:00
-- ignore events for some time after window in focus (mostly alt-tab)
2022-11-04 04:02:31 +00:00
if Current_time < Last_focus_time + 0.01 then
2022-07-25 22:33:06 +00:00
return
end
2022-09-03 21:13:22 +00:00
--
2023-12-07 05:32:10 +00:00
if Skip_rest_of_key_events then return end
if Current_app == ' run ' then
2022-12-24 03:30:06 +00:00
if run.key_release then run.key_release ( key , scancode ) end
2022-09-03 21:13:22 +00:00
elseif Current_app == ' source ' then
2022-12-24 03:30:06 +00:00
if source.key_release then source.key_release ( key , scancode ) end
2022-09-03 21:13:22 +00:00
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-20 21:06:08 +00:00
end
end
2022-09-03 21:13:22 +00:00
function App . mousepressed ( x , y , mouse_button )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-09-03 21:13:22 +00:00
--? print('mouse press', x,y)
if Current_app == ' run ' then
2022-12-24 04:43:30 +00:00
if run.mouse_press then run.mouse_press ( x , y , mouse_button ) end
2022-09-03 21:13:22 +00:00
elseif Current_app == ' source ' then
2022-12-24 04:43:30 +00:00
if source.mouse_press then source.mouse_press ( x , y , mouse_button ) end
2022-09-03 21:13:22 +00:00
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-07-20 21:06:08 +00:00
end
end
2022-08-24 20:27:04 +00:00
2022-09-03 21:13:22 +00:00
function App . mousereleased ( x , y , mouse_button )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
2022-12-24 01:16:19 +00:00
if run.mouse_release then run.mouse_release ( x , y , mouse_button ) end
2022-09-03 21:13:22 +00:00
elseif Current_app == ' source ' then
2022-12-24 01:16:19 +00:00
if source.mouse_release then source.mouse_release ( x , y , mouse_button ) end
2022-09-03 21:13:22 +00:00
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-08-24 20:27:04 +00:00
end
end
2022-08-31 16:38:49 +00:00
2024-05-20 05:40:27 +00:00
function App . mousemoved ( x , y , dx , dy , is_touch )
if current_app_is_warning ( ) then return end
if Current_app == ' run ' then
if run.mouse_move then run.mouse_move ( dx , dy ) end
elseif Current_app == ' source ' then
if source.mouse_move then source.mouse_move ( dx , dy ) end
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
end
end
2023-03-24 04:00:09 +00:00
function App . wheelmoved ( dx , dy )
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2023-03-24 04:00:09 +00:00
if Current_app == ' run ' then
if run.mouse_wheel_move then run.mouse_wheel_move ( dx , dy ) end
elseif Current_app == ' source ' then
if source.mouse_wheel_move then source.mouse_wheel_move ( dx , dy ) end
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
end
end
2024-05-20 05:41:52 +00:00
function App . mousefocus ( in_focus )
if current_app_is_warning ( ) then return end
if Current_app == ' run ' then
if run.mouse_focus then run.mouse_focus ( in_focus ) end
elseif Current_app == ' source ' then
if source.mouse_focus then source.mouse_focus ( in_focus ) end
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
end
end
2022-09-03 21:13:22 +00:00
function love . quit ( )
2024-01-12 11:51:34 +00:00
if Disable_all_quit_handlers then return end
2023-12-07 06:59:24 +00:00
if current_app_is_warning ( ) then return end
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
2023-09-08 21:16:50 +00:00
if Directory_error then return end
if Settings == nil then Settings = { } end
2022-09-10 05:31:27 +00:00
local source_settings = Settings.source
2022-09-10 05:30:37 +00:00
Settings = run.settings ( )
2022-09-03 21:13:22 +00:00
Settings.source = source_settings
else
Settings.source = source.settings ( )
end
Settings.current_app = Current_app
2023-09-08 15:22:45 +00:00
love.filesystem . write ( ' config ' , json.encode ( Settings ) )
2022-09-03 21:13:22 +00:00
if Current_app == ' run ' then
if run.quit then run.quit ( ) end
elseif Current_app == ' source ' then
if source.quit then source.quit ( ) end
else
assert ( false , ' unknown app " ' .. Current_app .. ' " ' )
2022-08-31 16:38:49 +00:00
end
end
2023-12-07 06:59:24 +00:00
function current_app_is_warning ( )
return type ( Current_app ) == ' table ' and Current_app.name == ' warning '
end
function show_warning ( message )
assert ( type ( Current_app ) == ' string ' )
Current_app = {
name = ' warning ' ,
message = message ,
next_app = Current_app ,
}
end
function clear_warning ( )
assert ( type ( Current_app ) == ' table ' )
Current_app = Current_app.next_app
end
2023-12-07 09:08:09 +00:00
function warning_message ( )
assert ( type ( Current_app ) == ' table ' )
return Current_app.message
end