2023-04-22 16:44:26 -05:00
var Debug = {
2023-12-13 19:53:09 -06:00
fn _break ( fn , obj ) {
if ( typeof fn !== 'function' ) return ;
obj ? ? = globalThis ;
var newfn = function ( ) {
console . log ( "broke" ) ;
fn ( ) ;
} ;
obj [ fn . name ] = newfn ;
} ,
2023-05-16 13:31:19 -05:00
draw _grid ( width , span , color ) {
color = color ? color : Color . green ;
cmd ( 47 , width , span , color ) ;
2023-04-22 16:44:26 -05:00
} ,
2023-12-15 12:45:09 -06:00
coordinate ( pos , size , color ) { GUI . text ( JSON . stringify ( pos . map ( p => Math . round ( p ) ) ) , pos , size , color ) ; } ,
2023-06-06 15:49:55 -05:00
boundingbox ( bb , color ) {
2023-08-14 17:20:30 -05:00
color ? ? = Color . white ;
2024-02-27 10:09:15 -06:00
cmd _points ( 0 , bbox . topoints ( bb ) , color ) ;
2023-06-06 15:49:55 -05:00
} ,
2023-04-22 16:44:26 -05:00
2023-12-18 06:45:27 -06:00
numbered _point ( pos , n , color ) {
color ? ? = Color . white ;
2024-02-25 17:31:48 -06:00
render . point ( pos , 3 , color ) ;
2023-12-18 06:45:27 -06:00
GUI . text ( n , pos . add ( [ 0 , 4 ] ) , 1 , color ) ;
2023-04-22 16:44:26 -05:00
} ,
phys _drawing : false ,
draw _phys ( on ) {
this . phys _drawing = on ;
cmd ( 4 , this . phys _drawing ) ;
} ,
draw _obj _phys ( obj ) {
cmd ( 82 , obj . body ) ;
} ,
2023-12-18 06:45:27 -06:00
gameobject ( go ) { cmd ( 15 , go . body ) ; } ,
2023-08-17 20:13:17 -05:00
draw _bb : false ,
draw _gizmos : false ,
draw _names : false ,
draw ( ) {
if ( this . draw _bb )
2023-11-29 12:40:13 -06:00
Game . all _objects ( function ( x ) { Debug . boundingbox ( x . boundingbox ( ) , Color . Debug . boundingbox . alpha ( 0.05 ) ) ; } ) ;
2023-08-17 20:13:17 -05:00
2023-10-04 08:18:09 -05:00
if ( Game . paused ( ) ) GUI . text ( "PAUSED" , [ 0 , 0 ] , 1 ) ;
2023-08-17 20:13:17 -05:00
if ( this . draw _gizmos )
2023-11-29 12:40:13 -06:00
Game . all _objects ( function ( x ) {
2023-08-17 20:13:17 -05:00
if ( ! x . icon ) return ;
2024-02-25 17:31:48 -06:00
GUI . image ( x . icon , Window . world2screen ( x . pos ) ) ;
2023-08-17 20:13:17 -05:00
} ) ;
if ( this . draw _names )
2023-11-29 12:40:13 -06:00
Game . all _objects ( function ( x ) {
2024-02-25 17:31:48 -06:00
GUI . text ( x , Window . world2screen ( x . pos ) . add ( [ 0 , 32 ] ) , 1 , Color . Debug . names ) ;
2023-08-17 20:13:17 -05:00
} ) ;
2023-08-24 16:22:52 -05:00
2023-09-12 12:45:54 -05:00
if ( Debug . Options . gif . rec ) {
2023-10-26 11:48:02 -05:00
GUI . text ( "REC" , [ 0 , 40 ] , 1 ) ;
GUI . text ( Time . seconds _to _timecode ( Time . time - Debug . Options . gif . start _time , Debug . Options . gif . fps ) , [ 0 , 30 ] , 1 ) ;
2023-09-12 12:45:54 -05:00
}
2023-09-12 00:02:57 -05:00
2023-10-04 08:18:09 -05:00
GUI . text ( Game . playing ( ) ? "PLAYING"
2023-08-27 21:57:19 -05:00
: Game . stepping ( ) ?
"STEP" :
Game . paused ( ) ?
2023-08-28 17:00:53 -05:00
"PAUSED; EDITING" :
"EDIT" , [ 0 , 0 ] , 1 ) ;
2023-08-17 20:13:17 -05:00
} ,
} ;
2023-12-18 17:12:05 -06:00
Debug . assert = function ( b , str )
{
str ? ? = "" ;
if ( ! b ) {
console . error ( ` Assertion failed. ${ str } ` ) ;
Game . quit ( ) ;
}
}
2023-08-17 20:13:17 -05:00
Debug . Options = { } ;
Debug . Options . Color = {
set trigger ( x ) { cmd ( 17 , x ) ; } ,
set debug ( x ) { cmd ( 16 , x ) ; } ,
2023-04-22 16:44:26 -05:00
} ;
var Gizmos = {
pick _gameobject _points ( worldpos , gameobject , points ) {
2023-11-29 17:31:41 -06:00
var idx = Math . grab _from _points ( worldpos , points . map ( gameobject . this2world , gameobject ) , 25 ) ;
2023-12-18 06:45:27 -06:00
if ( idx === - 1 ) return undefined ;
return idx ;
2023-04-22 16:44:26 -05:00
} ,
} ;
2024-03-01 11:45:06 -06:00
Object . assign ( performance , {
2023-09-11 02:46:12 -05:00
tick _now ( ) { return cmd ( 127 ) ; } ,
ns ( ticks ) { return cmd ( 128 , ticks ) ; } ,
us ( ticks ) { return cmd ( 129 , ticks ) ; } ,
ms ( ticks ) { return cmd ( 130 , ticks ) ; } ,
2023-12-18 06:45:27 -06:00
best _t ( ns ) {
var e = ns ;
var qq = 'ns' ;
if ( e > 1000 ) {
e /= 1000 ;
qq = 'us' ;
if ( e > 1000 ) {
e /= 1000 ;
qq = 'ms' ;
}
}
return {
time : e ,
unit : qq
} ;
} ,
2023-09-11 02:46:12 -05:00
cpu ( fn , times , q ) {
2023-06-07 08:41:09 -05:00
times ? ? = 1 ;
2023-12-18 06:45:27 -06:00
q ? ? = "unnamed" ;
2024-03-01 11:45:06 -06:00
var start = performance . tick _now ( ) ;
2023-06-07 08:41:09 -05:00
for ( var i = 0 ; i < times ; i ++ )
fn ( ) ;
2023-12-18 06:45:27 -06:00
2024-03-01 11:45:06 -06:00
var elapsed = performance . tick _now ( ) - start ;
var avgt = performance . best _t ( elapsed / times ) ;
var totalt = performance . best _t ( elapsed ) ;
2023-12-18 06:45:27 -06:00
2024-03-01 11:45:06 -06:00
console . say ( ` performance [ ${ q } ]: ${ avgt . time . toFixed ( 3 ) } ${ avgt . unit } average [ ${ totalt . time . toFixed ( 3 ) } ${ totalt . unit } for ${ times } loops] ` ) ;
2023-06-07 08:41:09 -05:00
} ,
2023-08-17 20:13:17 -05:00
get fps ( ) { return sys _cmd ( 8 ) ; } ,
2024-03-01 11:45:06 -06:00
measure ( fn , str ) {
str ? ? = 'unnamed' ;
var start = performance . tick _now ( ) ;
fn ( ) ;
var elapsed = performance . tick _now ( ) - start ;
elapsed = performance . best _t ( elapsed ) ;
say ( ` performance [ ${ str } ]: ${ elapsed . time . toFixed ( 3 ) } ${ elapsed . unit } ` ) ;
} ,
2024-02-25 17:31:48 -06:00
} ) ;
2023-04-22 16:44:26 -05:00
2024-03-01 11:45:06 -06:00
performance . test = {
barecall ( ) { performance ( 0 ) ; } ,
unpack _num ( n ) { performance ( 1 , n ) ; } ,
unpack _array ( n ) { performance ( 2 , n ) ; } ,
pack _num ( ) { performance ( 3 ) ; } ,
pack _string ( ) { performance ( 6 ) ; } ,
unpack _string ( s ) { performance ( 4 , s ) ; } ,
unpack _32farr ( a ) { performance ( 5 , a ) ; } ,
call _fn _n ( fn1 , n ) { performance ( 7 , fn1 , n , fn2 ) ; } ,
2023-12-18 06:45:27 -06:00
} ;
2024-03-01 11:45:06 -06:00
performance . test . call _fn _n . doc = "Calls fn1 n times, and then fn2." ;
2024-01-14 10:24:31 -06:00
2024-03-01 11:45:06 -06:00
performance . cpu . doc = ` Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution. ` ;
2023-10-23 08:08:11 -05:00
2023-08-28 17:00:53 -05:00
/* These controls are available during editing, and during play of debug builds */
2023-08-24 16:22:52 -05:00
var DebugControls = { } ;
2023-10-16 19:59:58 -05:00
DebugControls . toString = function ( ) { return "Debug" ; } ;
2023-08-24 16:22:52 -05:00
DebugControls . inputs = { } ;
DebugControls . inputs . f1 = function ( ) { Debug . draw _phys ( ! Debug . phys _drawing ) ; } ;
DebugControls . inputs . f1 . doc = "Draw physics debugging aids." ;
2023-09-20 08:11:14 -05:00
//DebugControls.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; };
//DebugControls.inputs.f3.doc = "Toggle drawing bounding boxes.";
2023-08-24 16:22:52 -05:00
DebugControls . inputs . f4 = function ( ) {
2023-10-11 17:22:41 -05:00
// Debug.draw_names = !Debug.draw_names;
// Debug.draw_gizmos = !Debug.draw_gizmos;
2023-08-24 16:22:52 -05:00
} ;
DebugControls . inputs . f4 . doc = "Toggle drawing gizmos and names of objects." ;
2023-09-12 00:02:57 -05:00
Debug . Options . gif = {
2023-09-12 12:45:54 -05:00
w : 640 , /* Max width */
h : 480 , /* Max height */
stretch : false , /* True if you want to stretch */
2023-09-13 07:31:00 -05:00
cpf : 4 ,
2023-09-14 12:49:29 -05:00
depth : 16 ,
2023-09-12 00:02:57 -05:00
file : "out.gif" ,
rec : false ,
2023-09-12 12:45:54 -05:00
secs : 6 ,
start _time : 0 ,
fps : 0 ,
start ( ) {
var w = this . w ;
var h = this . h ;
if ( ! this . stretch ) {
var win = Window . height / Window . width ;
var gif = h / w ;
if ( gif > win )
h = w * win ;
else
w = h / win ;
}
cmd ( 131 , w , h , this . cpf , this . depth ) ;
this . rec = true ;
this . fps = ( 1 / this . cpf ) * 100 ;
this . start _time = Time . time ;
2023-09-13 07:31:00 -05:00
timer . oneshot ( this . stop . bind ( this ) , this . secs , this , true ) ;
2023-09-12 12:45:54 -05:00
} ,
stop ( ) {
if ( ! this . rec ) return ;
cmd ( 132 , this . file ) ;
this . rec = false ;
} ,
2023-09-12 00:02:57 -05:00
} ;
2023-09-12 12:45:54 -05:00
2023-09-25 12:29:04 -05:00
DebugControls . inputs . f8 = function ( ) {
var now = new Date ( ) ;
Debug . Options . gif . file = now . toISOString ( ) + ".gif" ;
Debug . Options . gif . start ( ) ;
} ;
DebugControls . inputs . f9 = function ( ) {
Debug . Options . gif . stop ( ) ;
}
2023-09-12 00:02:57 -05:00
2023-08-24 16:22:52 -05:00
DebugControls . inputs . f10 = function ( ) { Time . timescale = 0.1 ; } ;
DebugControls . inputs . f10 . doc = "Toggle timescale to 1/10." ;
2023-08-27 21:57:19 -05:00
DebugControls . inputs . f10 . released = function ( ) { Time . timescale = 1.0 ; } ;
2024-02-25 17:31:48 -06:00
DebugControls . inputs . f12 = function ( ) { GUI . defaults . debug = ! GUI . defaults . debug ; console . warn ( "GUI toggle debug" ) ; } ;
2023-08-24 16:22:52 -05:00
DebugControls . inputs . f12 . doc = "Toggle drawing GUI debugging aids." ;
2024-02-25 17:31:48 -06:00
DebugControls . inputs [ 'M-1' ] = render . normal ;
DebugControls . inputs [ 'M-2' ] = render . wireframe ;
2023-08-17 20:13:17 -05:00
2023-08-28 17:00:53 -05:00
DebugControls . inputs [ 'C-M-f' ] = function ( ) { } ;
DebugControls . inputs [ 'C-M-f' ] . doc = "Enter camera fly mode." ;
2023-08-17 20:13:17 -05:00
var Time = {
set timescale ( x ) { cmd ( 3 , x ) ; } ,
2023-08-28 17:00:53 -05:00
get timescale ( ) { return cmd ( 121 ) ; } ,
2023-08-17 20:13:17 -05:00
set updateMS ( x ) { cmd ( 6 , x ) ; } ,
set physMS ( x ) { cmd ( 7 , x ) ; } ,
set renderMS ( x ) { cmd ( 5 , x ) ; } ,
2023-08-29 17:11:36 -05:00
2023-09-12 12:45:54 -05:00
get time ( ) { return cmd ( 133 ) ; } ,
seconds _to _timecode ( secs , fps )
{
var s = Math . trunc ( secs ) ;
secs -= s ;
var f = Math . trunc ( fps * secs ) ;
return ` ${ s } : ${ f } ` ;
} ,
2023-08-29 17:11:36 -05:00
pause ( ) {
2023-11-07 17:24:26 -06:00
Time . stash = Time . timescale ;
2023-08-29 17:11:36 -05:00
Time . timescale = 0 ;
} ,
play ( ) {
if ( ! Time . stash ) {
2024-02-25 17:31:48 -06:00
console . warn ( "Tried to resume time without calling Time.pause first." ) ;
2023-08-29 17:11:36 -05:00
return ;
}
Time . timescale = Time . stash ;
} ,
2023-05-24 20:45:50 -05:00
} ;
2023-10-23 08:08:11 -05:00
Time . doc = { } ;
Time . doc . timescale = "Get and set the timescale. 1 is normal time; 0.5 is half speed; etc." ;
Time . doc . updateMS = "Set the ms per game update." ;
Time . doc . physMS = "Set the ms per physics update." ;
Time . doc . renderMS = "Set the ms per render update." ;
Time . doc . time = "Seconds elapsed since the game started." ;
Time . doc . pause = "Pause the game by setting the timescale to 0; remembers the current timescale on play." ;
Time . doc . play = "Resume the game after using Time.pause." ;
2024-02-29 13:54:33 -06:00
player [ 0 ] . control ( DebugControls ) ;
2023-08-28 17:00:53 -05:00
Register . gui . register ( Debug . draw , Debug ) ;
2023-10-17 12:22:06 -05:00
2024-02-25 17:31:48 -06:00
Debug . api = { } ;
Debug . api . doc _entry = function ( obj , key )
2023-10-23 08:08:11 -05:00
{
2024-02-23 16:05:30 -06:00
if ( typeof key !== 'string' ) {
console . warn ( "Cannot print a key that isn't a string." ) ;
return undefined ;
}
2023-10-23 08:08:11 -05:00
var title = key ;
var o = obj [ key ] ;
if ( typeof o === 'undefined' && obj . impl && typeof obj . impl [ key ] !== 'undefined' )
o = obj . impl [ key ] ;
var t = typeof o ;
2024-02-23 16:05:30 -06:00
if ( Array . isArray ( o ) ) t = "array" ;
else if ( t === 'function' ) {
2023-10-23 08:08:11 -05:00
title = o . toString ( ) . tofirst ( ')' ) + ")" ;
2024-02-23 16:05:30 -06:00
title = title . fromfirst ( '(' ) ;
title = key + "(" + title ;
2023-10-23 08:08:11 -05:00
if ( o . doc ) doc = o . doc ;
t = "" ;
2024-02-23 16:05:30 -06:00
} else if ( t === 'undefined' ) t = "" ;
2023-10-23 08:08:11 -05:00
2024-02-23 16:05:30 -06:00
if ( t ) t = "**" + t + "**\n" ;
2023-10-23 08:08:11 -05:00
2024-02-23 16:05:30 -06:00
var doc = "" ;
if ( o . doc ) doc = o . doc ;
else if ( obj . doc && obj . doc [ key ] ) doc = obj . doc [ key ] ;
else if ( Array . isArray ( o ) ) doc = json . encode ( o ) ;
2023-10-23 08:08:11 -05:00
2024-02-23 16:05:30 -06:00
return ` ## ${ title }
2023-10-23 08:08:11 -05:00
$ { t }
$ { doc }
` ;
}
2024-02-25 17:31:48 -06:00
Debug . api . print _doc = function ( name )
2023-10-23 08:08:11 -05:00
{
2024-02-23 16:05:30 -06:00
var obj = name ;
if ( typeof name === 'string' ) {
obj = eval ( name ) ;
if ( ! obj ) {
console . warn ( ` Cannot print the API of ' ${ name } ', as it was not found. ` ) ;
return undefined ;
}
obj = globalThis [ name ] ;
}
obj = eval ( name ) ;
if ( ! Object . isObject ( obj ) ) {
console . warn ( "Cannot print the API of something that isn't an object." ) ;
return undefined ;
2023-10-23 08:08:11 -05:00
}
2024-02-23 16:05:30 -06:00
if ( ! obj ) {
console . warn ( ` Object ' ${ name } ' does not exist. ` ) ;
return ;
}
var mdoc = "# " + name + "\n" ;
2023-10-23 08:08:11 -05:00
if ( obj . doc ? . doc ) mdoc += obj . doc . doc + "\n" ;
else if ( typeof obj . doc === 'string' ) mdoc += obj . doc + "\n" ;
2024-02-23 16:05:30 -06:00
2023-10-23 08:08:11 -05:00
for ( var key in obj ) {
if ( key === 'doc' ) continue ;
2023-10-26 11:48:02 -05:00
if ( key === 'toString' ) continue ;
2024-02-23 16:05:30 -06:00
2024-02-25 17:31:48 -06:00
mdoc += Debug . api . doc _entry ( obj , key ) + "\n" ;
2023-10-23 08:08:11 -05:00
}
return mdoc ;
}
2024-02-27 10:09:15 -06:00
return {
Debug ,
Time ,
2024-03-01 11:45:06 -06:00
Gizmos ,
performance
2024-02-27 10:09:15 -06:00
}