2024-02-29 13:54:33 -06:00
render . doc = {
doc : "Functions for rendering modes." ,
normal : "Final render with all lighting." ,
wireframe : "Show only wireframes of models."
} ;
2024-07-11 14:25:45 -05:00
var cur = { } ;
2024-08-02 20:52:50 -05:00
render . use _shader = function use _shader ( shader )
2024-07-11 14:25:45 -05:00
{
2024-07-22 19:07:02 -05:00
if ( typeof shader === 'string' )
2024-08-02 20:52:50 -05:00
shader = make _shader ( shader ) ;
2024-07-11 14:25:45 -05:00
if ( cur . shader === shader ) return ;
cur . shader = shader ;
cur . bind = undefined ;
cur . mesh = undefined ;
render . setpipeline ( shader . pipe ) ;
2024-08-02 20:52:50 -05:00
shader _globals ( cur . shader ) ;
2024-07-11 14:25:45 -05:00
}
2024-08-02 20:52:50 -05:00
render . use _mat = function use _mat ( mat )
2024-07-11 14:25:45 -05:00
{
if ( ! cur . shader ) return ;
if ( cur . mat === mat ) return ;
2024-08-02 20:52:50 -05:00
shader _apply _material ( cur . shader , mat , cur . mat ) ;
2024-07-11 14:25:45 -05:00
cur . mat = mat ;
cur . images = [ ] ;
if ( ! cur . shader . fs . images ) return ;
for ( var img of cur . shader . fs . images )
if ( mat [ img . name ] )
cur . images . push ( mat [ img . name ] ) ;
else
cur . images . push ( game . texture ( "icons/no_tex.gif" ) ) ;
}
var models _array = [ ] ;
2024-08-02 20:52:50 -05:00
function set _model ( t )
2024-07-11 14:25:45 -05:00
{
if ( cur . shader . vs . unimap . model )
render . setunim4 ( 0 , cur . shader . vs . unimap . model . slot , t ) ;
}
2024-08-08 17:32:58 -05:00
render . set _model = set _model ;
2024-05-15 14:16:05 -05:00
var shaderlang = {
macos : "metal_macos" ,
2024-05-29 20:21:19 -05:00
windows : "hlsl5" ,
2024-05-16 14:50:18 -05:00
linux : "glsl430" ,
2024-05-21 18:50:53 -05:00
web : "wgsl" ,
2024-05-15 14:16:05 -05:00
ios : "metal_ios" ,
}
var attr _map = {
a _pos : 0 ,
a _uv : 1 ,
a _norm : 2 ,
2024-08-09 14:39:31 -05:00
a _joint : 3 ,
2024-05-15 14:16:05 -05:00
a _weight : 4 ,
a _color : 5 ,
a _tan : 6 ,
a _angle : 7 ,
a _wh : 8 ,
a _st : 9 ,
a _ppos : 10 ,
a _scale : 11
}
var blend _map = {
mix : true ,
none : false
}
var primitive _map = {
point : 1 ,
line : 2 ,
linestrip : 3 ,
triangle : 4 ,
trianglestrip : 5
}
var cull _map = {
none : 1 ,
front : 2 ,
back : 3
}
var depth _map = {
off : false ,
on : true
}
var face _map = {
cw : 2 ,
ccw : 1
}
2024-08-02 20:52:50 -05:00
render . poly _prim = function poly _prim ( verts )
2024-05-15 14:16:05 -05:00
{
var index = [ ] ;
if ( verts . length < 1 ) return undefined ;
for ( var i = 0 ; i < verts . length ; i ++ )
verts [ i ] [ 2 ] = 0 ;
for ( var i = 2 ; i < verts . length ; i ++ ) {
index . push ( 0 ) ;
index . push ( i - 1 ) ;
index . push ( i ) ;
}
return {
pos : os . make _buffer ( verts . flat ( ) ) ,
verts : verts . length ,
index : os . make _buffer ( index , 1 ) ,
count : index . length
} ;
}
function shader _directive ( shader , name , map )
{
var reg = new RegExp ( ` # ${ name } .* ` , 'g' ) ;
var mat = shader . match ( reg ) ;
2024-05-16 08:21:13 -05:00
if ( ! mat ) return undefined ;
2024-05-15 14:16:05 -05:00
reg = new RegExp ( ` # ${ name } \s * ` , 'g' ) ;
var ff = mat . map ( d => d . replace ( reg , '' ) ) [ 0 ] . trim ( ) ;
2024-05-16 08:21:13 -05:00
if ( map ) return map [ ff ] ;
return ff ;
2024-05-15 14:16:05 -05:00
}
2024-08-02 20:52:50 -05:00
var uni _globals = {
time ( stage , slot ) { render . setuniv ( stage , slot , profile . secs ( profile . now ( ) ) ) ; } ,
projection ( stage , slot ) { render . setuniproj ( stage , slot ) ; } ,
view ( stage , slot ) { render . setuniview ( stage , slot ) ; } ,
vp ( stage , slot ) { render . setunivp ( stage , slot ) ; } ,
}
function set _global _uni ( uni , stage ) {
uni _globals [ uni . name ] ? . ( stage , uni . slot ) ;
2024-05-15 14:16:05 -05:00
}
2024-07-14 16:09:50 -05:00
var setcam = render . set _camera ;
render . set _camera = function ( cam )
{
2024-07-23 12:02:46 -05:00
if ( nextflush ) {
nextflush ( ) ;
nextflush = undefined ;
}
2024-07-14 16:09:50 -05:00
delete cur . shader ;
setcam ( cam ) ;
}
2024-07-22 15:40:58 -05:00
var shader _cache = { } ;
2024-08-07 16:55:08 -05:00
var shader _times = { } ;
2024-08-02 20:52:50 -05:00
function strip _shader _inputs ( shader )
{
for ( var a of shader . vs . inputs )
a . name = a . name . slice ( 2 ) ;
}
2024-07-25 17:53:53 -05:00
2024-08-07 16:55:08 -05:00
render . hotreload = function ( )
{
for ( var i in shader _times ) {
if ( io . mod ( i ) <= shader _times [ i ] ) continue ;
say ( ` HOT RELOADING SHADER ${ i } ` ) ;
shader _times [ i ] = io . mod ( i ) ;
var obj = create _shader _obj ( i ) ;
obj = obj [ os . sys ( ) ] ;
2024-05-16 14:50:18 -05:00
obj . pipe = render . pipeline ( obj ) ;
2024-08-07 16:55:08 -05:00
var old = shader _cache [ i ] ;
Object . assign ( shader _cache [ i ] , obj ) ;
cur . bind = undefined ;
cur . mesh = undefined ;
2024-05-15 14:16:05 -05:00
}
2024-08-07 16:55:08 -05:00
}
function create _shader _obj ( file )
{
2024-05-15 14:16:05 -05:00
var files = [ file ] ;
2024-08-07 16:55:08 -05:00
var out = ".prosperon/tmp.shader" ;
var shader = io . slurp ( file ) ;
2024-05-30 17:12:32 -05:00
2024-05-15 14:16:05 -05:00
var incs = shader . match ( /#include <.*>/g ) ;
if ( incs )
for ( var inc of incs ) {
var filez = inc . match ( /#include <(.*)>/ ) [ 1 ] ;
var macro = io . slurp ( filez ) ;
2024-06-07 00:43:15 -05:00
if ( ! macro ) {
filez = ` shaders/ ${ filez } ` ;
macro = io . slurp ( filez ) ;
}
2024-05-15 14:16:05 -05:00
shader = shader . replace ( inc , macro ) ;
files . push ( filez ) ;
}
var blend = shader _directive ( shader , 'blend' , blend _map ) ;
var primitive = shader _directive ( shader , 'primitive' , primitive _map ) ;
var cull = shader _directive ( shader , 'cull' , cull _map ) ;
var depth = shader _directive ( shader , 'depth' , depth _map ) ;
var face = shader _directive ( shader , 'face' , face _map ) ;
2024-05-16 08:21:13 -05:00
var indexed = shader _directive ( shader , 'indexed' ) ;
if ( typeof indexed == 'undefined' ) indexed = true ;
if ( indexed === 'false' ) indexed = false ;
2024-05-15 14:16:05 -05:00
shader = shader . replace ( /uniform\s+(\w+)\s+(\w+);/g , "uniform _$2 { $1 $2; };" ) ;
shader = shader . replace ( /(texture2D|sampler) /g , "uniform $1 " ) ;
io . slurpwrite ( out , shader ) ;
2024-05-16 14:50:18 -05:00
var compiled = { } ;
// shader file is created, now cross compile to all targets
for ( var platform in shaderlang ) {
var backend = shaderlang [ platform ] ;
var ret = os . system ( ` sokol-shdc -f bare_yaml --slang= ${ backend } -i ${ out } -o ${ out } ` ) ;
if ( ret ) {
console . error ( ` error compiling shader ${ file } . No compilation found for ${ platform } : ${ backend } , and no cross compiler available. ` ) ;
return ;
}
2024-05-15 14:16:05 -05:00
/* Take YAML and create the shader object */
var yamlfile = ` ${ out } _reflection.yaml ` ;
2024-05-16 08:21:13 -05:00
var jjson = yaml . tojson ( io . slurp ( yamlfile ) ) ;
2024-05-30 17:12:32 -05:00
var obj = json . decode ( jjson ) ;
2024-05-15 14:16:05 -05:00
io . rm ( yamlfile ) ;
obj = obj . shaders [ 0 ] . programs [ 0 ] ;
function add _code ( stage ) {
stage . code = io . slurp ( stage . path ) ;
2024-05-16 14:50:18 -05:00
2024-05-15 14:16:05 -05:00
io . rm ( stage . path ) ;
delete stage . path ;
}
2024-06-03 16:45:08 -05:00
2024-05-15 14:16:05 -05:00
add _code ( obj . vs ) ;
2024-08-07 16:55:08 -05:00
if ( ! obj . fs && obj . vs . fs ) {
2024-05-15 14:16:05 -05:00
obj . fs = obj . vs . fs ;
delete obj . vs . fs ;
2024-08-07 16:55:08 -05:00
}
2024-05-15 14:16:05 -05:00
add _code ( obj . fs ) ;
obj . blend = blend ;
obj . cull = cull ;
obj . primitive = primitive ;
obj . depth = depth ;
obj . face = face ;
2024-05-16 08:21:13 -05:00
obj . indexed = indexed ;
2024-05-15 14:16:05 -05:00
if ( obj . vs . inputs )
for ( var i of obj . vs . inputs ) {
if ( ! ( i . name in attr _map ) )
i . mat = - 1 ;
else
i . mat = attr _map [ i . name ] ;
}
function make _unimap ( stage ) {
if ( ! stage . uniform _blocks ) return { } ;
var unimap = { } ;
for ( var uni of stage . uniform _blocks ) {
2024-05-16 14:50:18 -05:00
var uniname = uni . struct _name [ 0 ] == "_" ? uni . struct _name . slice ( 1 ) : uni . struct _name ;
2024-05-15 14:16:05 -05:00
2024-05-16 14:50:18 -05:00
unimap [ uniname ] = {
name : uniname ,
2024-05-15 14:16:05 -05:00
slot : Number ( uni . slot ) ,
size : Number ( uni . size )
} ;
}
return unimap ;
}
obj . vs . unimap = make _unimap ( obj . vs ) ;
obj . fs . unimap = make _unimap ( obj . fs ) ;
obj . name = file ;
2024-05-16 14:50:18 -05:00
2024-08-07 16:55:08 -05:00
strip _shader _inputs ( obj ) ;
2024-05-16 14:50:18 -05:00
compiled [ platform ] = obj ;
}
compiled . files = files ;
2024-08-07 16:55:08 -05:00
compiled . source = shader ;
2024-05-15 14:16:05 -05:00
2024-08-07 16:55:08 -05:00
return compiled ;
}
function make _shader ( shader )
{
if ( shader _cache [ shader ] ) return shader _cache [ shader ] ;
var file = shader ;
shader = io . slurp ( file ) ;
if ( ! shader ) {
console . info ( ` not found! slurping shaders/ ${ file } ` ) ;
shader = io . slurp ( ` shaders/ ${ file } ` ) ;
}
var writejson = ` .prosperon/ ${ file . name ( ) } .shader.json ` ;
profile . cache ( "shader" , file ) ;
2024-05-15 14:16:05 -05:00
2024-08-07 16:55:08 -05:00
breakme : if ( io . exists ( writejson ) ) {
var data = json . decode ( io . slurp ( writejson ) ) ;
var filemod = io . mod ( writejson ) ;
if ( ! data . files ) break breakme ;
for ( var i of data . files ) {
if ( io . mod ( i ) > filemod ) {
break breakme ;
}
}
profile . endcache ( " [cached]" ) ;
var shaderobj = json . decode ( io . slurp ( writejson ) ) ;
var obj = shaderobj [ os . sys ( ) ] ;
obj . pipe = render . pipeline ( obj ) ;
shader _cache [ file ] = obj ;
shader _times [ file ] = io . mod ( file ) ;
return obj ;
}
var compiled = create _shader _obj ( file ) ;
io . slurpwrite ( writejson , json . encode ( compiled ) ) ;
2024-05-16 14:50:18 -05:00
var obj = compiled [ os . sys ( ) ] ;
2024-05-15 14:16:05 -05:00
obj . pipe = render . pipeline ( obj ) ;
2024-08-07 16:55:08 -05:00
shader _cache [ file ] = obj ;
shader _times [ file ] = io . mod ( file ) ;
2024-05-15 14:16:05 -05:00
return obj ;
}
var shader _unisize = {
4 : render . setuniv ,
8 : render . setuniv2 ,
12 : render . setuniv3 ,
16 : render . setuniv4
} ;
2024-08-02 20:52:50 -05:00
function shader _globals ( shader )
{
for ( var p in shader . vs . unimap )
set _global _uni ( shader . vs . unimap [ p ] , 0 ) ;
for ( var p in shader . fs . unimap )
set _global _uni ( shader . fs . unimap [ p ] , 1 ) ;
}
2024-05-15 14:16:05 -05:00
2024-08-02 20:52:50 -05:00
function shader _apply _material ( shader , material = { } , old = { } )
2024-05-15 14:16:05 -05:00
{
for ( var p in shader . vs . unimap ) {
2024-08-02 20:52:50 -05:00
if ( ! ( p in material ) ) continue ;
2024-07-11 14:25:45 -05:00
if ( material [ p ] === old [ p ] ) continue ;
assert ( p in material , ` shader ${ shader . name } has no uniform for ${ p } ` ) ;
2024-05-15 14:16:05 -05:00
var s = shader . vs . unimap [ p ] ;
2024-08-09 14:39:31 -05:00
if ( p === 'bones' ) {
render . setunibones ( 0 , s . slot , material [ p ] ) ;
continue ;
}
2024-05-15 14:16:05 -05:00
shader _unisize [ s . size ] ( 0 , s . slot , material [ p ] ) ;
}
for ( var p in shader . fs . unimap ) {
2024-08-02 20:52:50 -05:00
if ( ! ( p in material ) ) continue ;
2024-07-11 14:25:45 -05:00
if ( material [ p ] === old [ p ] ) continue ;
assert ( p in material , ` shader ${ shader . name } has no uniform for ${ p } ` ) ;
2024-05-15 14:16:05 -05:00
var s = shader . fs . unimap [ p ] ;
shader _unisize [ s . size ] ( 1 , s . slot , material [ p ] ) ;
}
2024-07-11 14:25:45 -05:00
2024-06-19 18:52:41 -05:00
if ( ! material . diffuse ) return ;
2024-07-11 14:25:45 -05:00
if ( material . diffuse === old . diffuse ) return ;
2024-05-15 14:16:05 -05:00
if ( "diffuse_size" in shader . fs . unimap )
render . setuniv2 ( 1 , shader . fs . unimap . diffuse _size . slot , [ material . diffuse . width , material . diffuse . height ] ) ;
2024-06-19 18:52:41 -05:00
2024-05-15 14:16:05 -05:00
if ( "diffuse_size" in shader . vs . unimap )
2024-06-19 18:52:41 -05:00
render . setuniv2 ( 0 , shader . vs . unimap . diffuse _size . slot , [ material . diffuse . width , material . diffuse . height ] ) ;
2024-05-15 14:16:05 -05:00
}
2024-08-02 20:52:50 -05:00
function sg _bind ( mesh , ssbo )
2024-05-15 14:16:05 -05:00
{
2024-07-11 14:25:45 -05:00
cur . mesh = mesh ;
2024-05-15 14:16:05 -05:00
var bind = { } ;
bind . attrib = [ ] ;
2024-07-11 14:25:45 -05:00
if ( cur . shader . vs . inputs )
for ( var a of cur . shader . vs . inputs ) {
2024-05-15 14:16:05 -05:00
if ( ! ( a . name in mesh ) ) {
2024-08-07 16:55:08 -05:00
console . error ( ` cannot draw shader ${ cur . shader . name } ; there is no attrib ${ a . name } in the given mesh. ${ json . encode ( mesh ) } ` ) ;
2024-08-02 20:52:50 -05:00
return undefined ;
2024-05-15 14:16:05 -05:00
} else
2024-08-02 20:52:50 -05:00
bind . attrib . push ( mesh [ a . name ] ) ;
2024-05-15 14:16:05 -05:00
}
2024-07-11 14:25:45 -05:00
if ( cur . shader . indexed ) {
2024-05-15 14:16:05 -05:00
bind . index = mesh . index ;
bind . count = mesh . count ;
} else
bind . count = mesh . verts ;
bind . ssbo = [ ] ;
2024-07-11 14:25:45 -05:00
if ( cur . shader . vs . storage _buffers )
for ( var b of cur . shader . vs . storage _buffers )
2024-05-15 14:16:05 -05:00
bind . ssbo . push ( ssbo ) ;
2024-07-11 14:25:45 -05:00
bind . inst = 1 ;
bind . images = cur . images ;
cur . bind = bind ;
render . setbind ( cur . bind ) ;
2024-05-15 14:16:05 -05:00
return bind ;
}
2024-05-16 08:21:13 -05:00
render . device = {
pc : [ 1920 , 1080 ] ,
macbook _m2 : [ 2560 , 1664 , 13.6 ] ,
ds _top : [ 400 , 240 , 3.53 ] ,
ds _bottom : [ 320 , 240 , 3.02 ] ,
playdate : [ 400 , 240 , 2.7 ] ,
switch : [ 1280 , 720 , 6.2 ] ,
switch _lite : [ 1280 , 720 , 5.5 ] ,
switch _oled : [ 1280 , 720 , 7 ] ,
dsi : [ 256 , 192 , 3.268 ] ,
ds : [ 256 , 192 , 3 ] ,
dsixl : [ 256 , 192 , 4.2 ] ,
ipad _air _m2 : [ 2360 , 1640 , 11.97 ] ,
iphone _se : [ 1334 , 750 , 4.7 ] ,
iphone _12 _pro : [ 2532 , 1170 , 6.06 ] ,
iphone _15 : [ 2556 , 1179 , 6.1 ] ,
gba : [ 240 , 160 , 2.9 ] ,
gameboy : [ 160 , 144 , 2.48 ] ,
gbc : [ 160 , 144 , 2.28 ] ,
steamdeck : [ 1280 , 800 , 7 ] ,
vita : [ 960 , 544 , 5 ] ,
psp : [ 480 , 272 , 4.3 ] ,
imac _m3 : [ 4480 , 2520 , 23.5 ] ,
macbook _pro _m3 : [ 3024 , 1964 , 14.2 ] ,
ps1 : [ 320 , 240 , 5 ] ,
ps2 : [ 640 , 480 ] ,
snes : [ 256 , 224 ] ,
gamecube : [ 640 , 480 ] ,
n64 : [ 320 , 240 ] ,
c64 : [ 320 , 200 ] ,
macintosh : [ 512 , 342 , 9 ] ,
gamegear : [ 160 , 144 , 3.2 ] ,
} ;
render . device . doc = ` Device resolutions given as [x,y,inches diagonal]. ` ;
2024-06-07 00:43:15 -05:00
var textshader ;
var circleshader ;
var polyshader ;
2024-07-09 01:03:39 -05:00
var slice9shader ;
2024-07-18 12:39:58 -05:00
var parshader ;
2024-07-22 19:07:02 -05:00
var spritessboshader ;
2024-07-23 12:02:46 -05:00
var polyssboshader ;
2024-06-07 00:43:15 -05:00
2024-07-23 17:21:27 -05:00
var sprite _ssbo ;
2024-06-07 00:43:15 -05:00
render . init = function ( ) {
2024-08-02 20:52:50 -05:00
textshader = make _shader ( "shaders/text_base.cg" ) ;
render . spriteshader = make _shader ( "shaders/sprite.cg" ) ;
spritessboshader = make _shader ( "shaders/sprite_ssbo.cg" ) ;
render . postshader = make _shader ( "shaders/simplepost.cg" ) ;
slice9shader = make _shader ( "shaders/9slice.cg" ) ;
circleshader = make _shader ( "shaders/circle.cg" ) ;
polyshader = make _shader ( "shaders/poly.cg" ) ;
parshader = make _shader ( "shaders/baseparticle.cg" ) ;
polyssboshader = make _shader ( "shaders/poly_ssbo.cg" ) ;
2024-07-23 12:02:46 -05:00
poly _ssbo = render . make _textssbo ( ) ;
2024-07-23 17:21:27 -05:00
sprite _ssbo = render . make _textssbo ( ) ;
2024-06-07 00:43:15 -05:00
render . textshader = textshader ;
2024-06-07 09:49:13 -05:00
os . make _circle2d ( ) . draw = function ( ) {
render . circle ( this . body ( ) . transform ( ) . pos , this . radius , [ 1 , 1 , 0 , 1 ] ) ;
}
var disabled = [ 148 / 255 , 148 / 255 , 148 / 255 , 1 ] ;
var sleep = [ 1 , 140 / 255 , 228 / 255 , 1 ] ;
var dynamic = [ 1 , 70 / 255 , 46 / 255 , 1 ] ;
var kinematic = [ 1 , 194 / 255 , 64 / 255 , 1 ] ;
var static _color = [ 73 / 255 , 209 / 255 , 80 / 255 , 1 ] ;
os . make _poly2d ( ) . draw = function ( ) {
var body = this . body ( ) ;
var color = body . sleeping ( ) ? [ 0 , 0.3 , 0 , 0.4 ] : [ 0 , 1 , 0 , 0.4 ] ;
var t = body . transform ( ) ;
render . poly ( this . points , color , body . transform ( ) ) ;
color . a = 1 ;
render . line ( this . points . wrapped ( 1 ) , color , 1 , body . transform ( ) ) ;
}
os . make _seg2d ( ) . draw = function ( ) {
render . line ( [ this . a ( ) , this . b ( ) ] , [ 1 , 0 , 1 , 1 ] , Math . max ( this . radius / 2 , 1 ) , this . body ( ) . transform ( ) ) ;
}
joint . pin ( ) . draw = function ( ) {
var a = this . bodyA ( ) ;
var b = this . bodyB ( ) ;
render . line ( [ a . transform ( ) . pos . xy , b . transform ( ) . pos . xy ] , [ 0 , 1 , 1 , 1 ] , 1 ) ;
}
2024-06-07 00:43:15 -05:00
}
2024-08-25 14:23:22 -05:00
render . draw _sprites = true ;
render . draw _particles = true ;
render . draw _hud = true ;
render . draw _gui = true ;
2024-08-26 11:13:26 -05:00
render . draw _gizmos = true ;
2024-08-25 14:23:22 -05:00
2024-08-02 20:52:50 -05:00
render . sprites = function render _sprites ( gridsize = 1 )
2024-07-23 17:21:27 -05:00
{
2024-08-22 14:41:01 -05:00
// When y sorting, draw layer is firstly important followed by the gameobject position
2024-08-22 14:43:04 -05:00
var buckets ;
if ( render . y _sort ) {
2024-08-22 14:41:01 -05:00
profile . frame ( "y bucketing" ) ;
var sps = Object . values ( allsprites ) ;
2024-08-22 14:43:04 -05:00
buckets = { } ;
2024-08-22 14:41:01 -05:00
for ( var sprite of sps ) {
var layer = ( sprite . gameobject . drawlayer * 10000 ) - sprite . gameobject . pos . y ;
buckets [ layer ] ? ? = { } ;
if ( buckets [ layer ] [ sprite . path ] )
buckets [ layer ] [ sprite . path ] . push ( sprite ) ;
else
buckets [ layer ] [ sprite . path ] = [ sprite ] ;
}
profile . endframe ( ) ;
profile . frame ( "y sorting" ) ;
buckets = Object . entries ( buckets ) . sort ( ( a , b ) => {
var na = Number ( a [ 0 ] ) ;
var nb = Number ( b [ 0 ] ) ;
if ( na < nb ) return - 1 ;
return 1 ;
} ) ;
profile . endframe ( ) ;
2024-08-22 14:43:04 -05:00
} else {
profile . frame ( "sorting" ) ;
var sprite _buckets = component . sprite _buckets ( ) ;
var buckets = Object . entries ( sprite _buckets ) . sort ( ( a , b ) => {
var na = Number ( a [ 0 ] ) ;
var nb = Number ( b [ 0 ] ) ;
if ( na < nb ) return - 1 ;
return 1 ;
} ) ;
profile . endframe ( ) ;
}
2024-08-02 20:52:50 -05:00
/ *
2024-07-25 10:33:51 -05:00
profile . frame ( "bucketing" ) ;
2024-07-23 17:21:27 -05:00
var sps = Object . values ( allsprites ) ;
2024-08-02 20:52:50 -05:00
var buckets = [ ] ;
for ( var i = 0 ; i <= 20 ; i ++ )
buckets [ i ] = { } ;
2024-07-23 17:21:27 -05:00
for ( var sprite of sps ) {
2024-08-02 20:52:50 -05:00
var layer = sprite . gameobject . drawlayer + 10 ;
if ( buckets [ layer ] [ sprite . path ] )
buckets [ layer ] [ sprite . path ] . push ( sprite ) ;
else
buckets [ layer ] [ sprite . path ] = [ sprite ] ;
2024-07-23 17:21:27 -05:00
}
2024-07-25 10:33:51 -05:00
profile . endframe ( ) ;
2024-08-22 14:41:01 -05:00
* /
2024-07-25 10:33:51 -05:00
profile . frame ( "drawing" ) ;
2024-07-23 17:21:27 -05:00
render . use _shader ( spritessboshader ) ;
2024-08-02 20:52:50 -05:00
for ( var layer of buckets ) {
for ( var img of Object . values ( layer [ 1 ] ) ) {
2024-07-23 17:21:27 -05:00
var sparray = Object . values ( img ) ;
if ( sparray . length === 0 ) continue ;
var ss = sparray [ 0 ] ;
render . use _mat ( ss ) ;
2024-08-02 20:52:50 -05:00
render . make _sprite _ssbo ( sparray , sprite _ssbo ) ;
2024-07-23 17:21:27 -05:00
render . draw ( shape . quad , sprite _ssbo , sparray . length ) ;
2024-08-15 12:26:37 -05:00
if ( debug . sprite _nums ) render . text ( ss . diffuse . getid ( ) , ss . transform . pos ) ;
2024-07-23 17:21:27 -05:00
}
}
2024-07-25 10:33:51 -05:00
profile . endframe ( ) ;
}
2024-07-23 17:21:27 -05:00
2024-08-07 16:55:08 -05:00
render . circle = function render _circle ( pos , radius , color , inner _radius = 1 ) {
2024-09-14 09:36:40 -05:00
check _flush ( undefined ) ;
2024-08-07 16:55:08 -05:00
if ( inner _radius >= 1 )
inner _radius = inner _radius / radius ;
else if ( inner _radius < 0 )
inner _radius = 1.0 ;
2024-06-07 00:43:15 -05:00
var mat = {
radius : radius ,
2024-08-07 16:55:08 -05:00
inner _r : inner _radius ,
2024-06-07 00:43:15 -05:00
coord : pos ,
2024-08-07 16:55:08 -05:00
shade : color ,
2024-06-07 00:43:15 -05:00
} ;
2024-07-11 14:25:45 -05:00
render . use _shader ( circleshader ) ;
render . use _mat ( mat ) ;
render . draw ( shape . quad ) ;
2024-06-07 00:43:15 -05:00
}
2024-08-07 16:55:08 -05:00
render . circle . doc = "Draw a circle at pos, with a given radius and color. If inner_radius is between 0 and 1, it acts as a percentage of radius. If it is above 1, is acts as a unit (usually a pixel)." ;
2024-06-07 00:43:15 -05:00
2024-08-02 20:52:50 -05:00
render . poly = function render _poly ( points , color , transform ) {
2024-06-07 00:43:15 -05:00
var buffer = render . poly _prim ( points ) ;
var mat = { shade : color } ;
2024-07-11 14:25:45 -05:00
render . use _shader ( polyshader ) ;
2024-08-02 20:52:50 -05:00
set _model ( transform ) ;
2024-07-11 14:25:45 -05:00
render . use _mat ( mat ) ;
render . draw ( buffer ) ;
2024-06-07 00:43:15 -05:00
}
2024-07-23 12:02:46 -05:00
var nextflush = undefined ;
2024-08-02 20:52:50 -05:00
function flush ( )
{
nextflush ? . ( ) ;
nextflush = undefined ;
}
function check _flush ( flush _fn )
2024-07-23 12:02:46 -05:00
{
if ( ! nextflush )
nextflush = flush _fn ;
else if ( nextflush !== flush _fn ) {
2024-08-02 20:52:50 -05:00
nextflush ( ) ;
nextflush = flush _fn ;
}
2024-07-23 12:02:46 -05:00
}
2024-09-13 10:27:01 -05:00
render . flush = check _flush ;
2024-07-23 12:02:46 -05:00
var poly _cache = [ ] ;
2024-08-02 20:52:50 -05:00
var poly _idx = 0 ;
2024-07-23 12:02:46 -05:00
var poly _ssbo ;
2024-08-02 20:52:50 -05:00
function poly _e ( )
{
var e ;
poly _idx ++ ;
if ( poly _idx > poly _cache . length ) {
e = {
transform : os . make _transform ( ) ,
color : Color . white
} ;
poly _cache . push ( e ) ;
return e ;
}
var e = poly _cache [ poly _idx - 1 ] ;
e . transform . unit ( ) ;
return e ;
}
function flush _poly ( )
2024-07-23 12:02:46 -05:00
{
2024-08-02 20:52:50 -05:00
if ( poly _idx === 0 ) return ;
2024-07-23 12:02:46 -05:00
render . use _shader ( polyssboshader ) ;
render . use _mat ( { } ) ;
2024-08-02 20:52:50 -05:00
render . make _particle _ssbo ( poly _cache . slice ( 0 , poly _idx ) , poly _ssbo ) ;
2024-08-24 18:40:29 -05:00
render . draw ( shape . centered _quad , poly _ssbo , poly _idx ) ;
2024-08-02 20:52:50 -05:00
poly _idx = 0 ;
2024-07-23 12:02:46 -05:00
}
2024-08-02 20:52:50 -05:00
render . line = function render _line ( points , color = Color . white , thickness = 1 ) {
2024-08-28 16:38:31 -05:00
for ( var i = 0 ; i < points . length - 1 ; i ++ ) {
var a = points [ i ] ;
var b = points [ i + 1 ] ;
var poly = poly _e ( ) ;
var dist = vector . distance ( a , b ) ;
poly . transform . move ( vector . midpoint ( a , b ) ) ;
poly . transform . rotate ( [ 0 , 0 , - 1 ] , vector . angle ( [ b . x - a . x , b . y - a . y ] ) ) ;
poly . transform . scale = [ dist , thickness , 1 ] ;
poly . color = color ;
}
2024-08-02 20:52:50 -05:00
check _flush ( flush _poly ) ;
2024-06-07 00:43:15 -05:00
}
2024-05-16 08:21:13 -05:00
/* All draw in screen space */
render . point = function ( pos , size , color = Color . blue ) {
2024-05-30 12:05:51 -05:00
render . circle ( pos , size , size , color ) ;
2024-05-16 08:21:13 -05:00
} ;
2024-08-02 20:52:50 -05:00
render . cross = function render _cross ( pos , size , color = Color . red , thickness = 1 ) {
2024-05-21 09:33:17 -05:00
var a = [
pos . add ( [ 0 , size ] ) ,
pos . add ( [ 0 , - size ] )
] ;
var b = [
pos . add ( [ size , 0 ] ) ,
pos . add ( [ - size , 0 ] )
] ;
2024-07-03 16:38:29 -05:00
render . line ( a , color , thickness ) ;
render . line ( b , color , thickness ) ;
2024-05-21 09:33:17 -05:00
} ;
2024-05-16 08:21:13 -05:00
2024-08-02 20:52:50 -05:00
render . arrow = function render _arrow ( start , end , color = Color . red , wingspan = 4 , wingangle = 10 ) {
2024-05-16 08:21:13 -05:00
var dir = end . sub ( start ) . normalized ( ) ;
var wing1 = [
Vector . rotate ( dir , wingangle ) . scale ( wingspan ) . add ( end ) ,
end
] ;
var wing2 = [
Vector . rotate ( dir , - wingangle ) . scale ( wingspan ) . add ( end ) ,
end
] ;
render . line ( [ start , end ] , color ) ;
render . line ( wing1 , color ) ;
render . line ( wing2 , color ) ;
} ;
2024-08-02 20:52:50 -05:00
render . coordinate = function render _coordinate ( pos , size , color ) {
2024-05-16 08:21:13 -05:00
render . text ( JSON . stringify ( pos . map ( p => Math . round ( p ) ) ) , pos , size , color ) ;
render . point ( pos , 2 , color ) ;
}
2024-08-02 20:52:50 -05:00
render . boundingbox = function render _boundingbox ( bb , color = Color . white ) {
2024-07-10 09:39:28 -05:00
render . line ( bbox . topoints ( bb ) . wrapped ( 1 ) , color ) ;
2024-05-16 08:21:13 -05:00
}
2024-08-02 20:52:50 -05:00
render . rectangle = function render _rectangle ( lowerleft , upperright , color ) {
2024-07-23 14:30:41 -05:00
var transform = os . make _transform ( ) ;
var wh = [ upperright . x - lowerleft . x , upperright . y - lowerleft . y ] ;
2024-08-02 20:52:50 -05:00
var poly = poly _e ( ) ;
poly . transform . move ( vector . midpoint ( lowerleft , upperright ) ) ;
poly . transform . scale = [ wh . x , wh . y , 1 ] ;
poly . color = color ;
check _flush ( flush _poly ) ;
2024-05-16 08:21:13 -05:00
} ;
2024-08-02 20:52:50 -05:00
render . box = function render _box ( pos , wh , color = Color . white ) {
var poly = poly _e ( ) ;
poly . transform . move ( pos ) ;
poly . transform . scale = [ wh . x , wh . y , 1 ] ;
poly . color = color ;
check _flush ( flush _poly ) ;
2024-05-16 08:21:13 -05:00
} ;
2024-08-02 20:52:50 -05:00
render . window = function render _window ( pos , wh , color ) { render . box ( pos . add ( wh . scale ( 0.5 ) ) , wh , color ) ; } ;
2024-05-16 08:21:13 -05:00
2024-07-09 13:48:15 -05:00
render . text _bb = function ( str , size = 1 , wrap = - 1 , pos = [ 0 , 0 ] )
{
var bb = render . text _size ( str , size , wrap ) ;
2024-07-09 01:03:39 -05:00
var w = ( bb . r - bb . l ) ;
var h = ( bb . t - bb . b ) ;
2024-07-09 13:48:15 -05:00
2024-07-09 01:03:39 -05:00
bb . r += pos . x ;
bb . l += pos . x ;
bb . t += pos . y ;
bb . b += pos . y ;
2024-07-09 13:48:15 -05:00
return bb ;
}
render . text = function ( str , pos , size = 1 , color = Color . white , wrap = - 1 , anchor = [ 0 , 1 ] , cursor = - 1 ) {
2024-07-10 09:39:28 -05:00
var bb = render . text _bb ( str , size , wrap , pos ) ;
2024-09-06 22:47:04 -05:00
gui . text ( str , pos , size , color , wrap , cursor ) ; // this puts text into buffer
2024-07-23 12:02:46 -05:00
check _flush ( render . flush _text ) ;
2024-07-09 01:03:39 -05:00
return bb ;
2024-05-16 08:21:13 -05:00
p . x -= w * anchor . x ;
bb . r += ( w * anchor . x ) ;
bb . l += ( w * anchor . x ) ;
p . y += h * ( 1 - anchor . y ) ;
bb . t += h * ( 1 - anchor . y ) ;
bb . b += h * ( 1 - anchor . y ) ;
2024-07-09 01:03:39 -05:00
2024-05-16 08:21:13 -05:00
return bb ;
} ;
2024-07-09 16:43:09 -05:00
render . image = function ( tex , pos , scale = [ tex . width , tex . height ] , rotation = 0 , color = Color . white ) {
2024-09-13 14:34:54 -05:00
if ( typeof tex === 'string' ) {
2024-09-11 12:25:42 -05:00
tex = game . texture ( tex ) ;
2024-09-13 14:34:54 -05:00
scale . x ? ? = tex . width ;
scale . y ? ? = tex . height ;
}
2024-09-11 12:25:42 -05:00
if ( ! tex ) return ;
2024-08-02 20:52:50 -05:00
flush ( ) ;
2024-06-26 16:57:17 -05:00
var t = os . make _transform ( ) ;
t . pos = pos ;
2024-07-09 16:43:09 -05:00
t . scale = [ scale . x / tex . width , scale . y / tex . height , 1 ] ;
2024-07-11 14:25:45 -05:00
render . use _shader ( render . spriteshader ) ;
2024-08-02 20:52:50 -05:00
set _model ( t ) ;
2024-07-11 14:25:45 -05:00
render . use _mat ( {
2024-06-26 16:57:17 -05:00
shade : color ,
2024-07-14 16:09:50 -05:00
diffuse : tex ,
rect : [ 0 , 0 , 1 , 1 ]
2024-06-26 16:57:17 -05:00
} ) ;
2024-07-11 14:25:45 -05:00
render . draw ( shape . quad ) ;
2024-07-09 01:03:39 -05:00
var bb = { } ;
bb . b = pos . y ;
bb . l = pos . x ;
bb . t = pos . y + tex . height * scale ;
bb . r = pos . x + tex . width * scale ;
return bb ;
}
2024-07-15 15:54:18 -05:00
// pos is the lower left corner, scale is the width and height
2024-07-09 16:43:09 -05:00
render . slice9 = function ( tex , pos , bb , scale = [ tex . width , tex . height ] , color = Color . white )
2024-07-09 01:03:39 -05:00
{
var t = os . make _transform ( ) ;
t . pos = pos ;
2024-07-09 16:43:09 -05:00
t . scale = [ scale . x / tex . width , scale . y / tex . height , 1 ] ;
var border ;
if ( typeof bb === 'number' )
border = [ bb / tex . width , bb / tex . height , bb / tex . width , bb / tex . height ] ;
else
border = [ bb . l / tex . width , bb . b / tex . height , bb . r / tex . width , bb . t / tex . height ] ;
2024-07-11 14:25:45 -05:00
render . use _shader ( slice9shader ) ;
2024-08-02 20:52:50 -05:00
set _model ( t ) ;
2024-07-11 14:25:45 -05:00
render . use _mat ( {
2024-07-09 13:48:15 -05:00
shade : color ,
diffuse : tex ,
rect : [ 0 , 0 , 1 , 1 ] ,
2024-07-09 16:43:09 -05:00
border : border ,
scale : [ scale . x / tex . width , scale . y / tex . height ]
2024-07-09 01:03:39 -05:00
} ) ;
2024-07-11 14:25:45 -05:00
render . draw ( shape . quad ) ;
2024-07-09 01:03:39 -05:00
}
2024-09-06 22:47:04 -05:00
function endframe ( )
{
tdraw = 0 ;
}
var textssbos = [ ] ;
var tdraw = 0 ;
2024-07-18 17:09:35 -05:00
2024-07-09 01:03:39 -05:00
render . flush _text = function ( )
{
if ( ! render . textshader ) return ;
2024-09-06 22:47:04 -05:00
tdraw ++ ;
if ( textssbos . length < tdraw )
textssbos . push ( render . make _textssbo ( ) ) ;
2024-09-07 00:11:34 -05:00
var textssbo = textssbos [ tdraw - 1 ] ;
2024-09-06 22:47:04 -05:00
var amt = render . flushtext ( textssbo ) ; // load from buffer into ssbo
if ( amt === 0 ) {
tdraw -- ;
return ;
}
2024-07-18 17:09:35 -05:00
2024-07-11 14:25:45 -05:00
render . use _shader ( render . textshader ) ;
render . use _mat ( { text : render . font . texture } ) ;
2024-07-18 17:09:35 -05:00
render . draw ( shape . quad , textssbo , amt ) ;
2024-05-16 08:21:13 -05:00
}
2024-08-02 20:52:50 -05:00
var fontcache = { } ;
2024-05-16 08:21:13 -05:00
render . set _font = function ( path , size ) {
var fontstr = ` ${ path } - ${ size } ` ;
2024-08-02 20:52:50 -05:00
if ( render . font && fontcache [ fontstr ] === render . font ) return ;
if ( ! fontcache [ fontstr ] ) fontcache [ fontstr ] = os . make _font ( path , size ) ;
2024-07-09 01:03:39 -05:00
render . flush _text ( ) ;
2024-05-16 08:21:13 -05:00
2024-08-02 20:52:50 -05:00
gui . font _set ( fontcache [ fontstr ] ) ;
render . font = fontcache [ fontstr ] ;
2024-05-16 08:21:13 -05:00
}
render . doc = "Draw shapes in screen space." ;
render . cross . doc = "Draw a cross centered at pos, with arm length size." ;
render . arrow . doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle." ;
render . rectangle . doc = "Draw a rectangle, with its corners at lowerleft and upperright." ;
2024-09-07 00:11:34 -05:00
render . draw = function render _draw ( mesh , ssbo , inst = 1 , e _start = 0 )
2024-07-11 14:25:45 -05:00
{
2024-08-02 20:52:50 -05:00
sg _bind ( mesh , ssbo ) ;
profile . frame ( "gpu" ) ;
2024-09-07 00:11:34 -05:00
render . spdraw ( e _start , cur . bind . count , inst ) ;
2024-08-02 20:52:50 -05:00
profile . endframe ( ) ;
2024-07-11 14:25:45 -05:00
}
2024-05-16 08:21:13 -05:00
2024-07-25 17:53:53 -05:00
// Returns an array in the form of [left, bottom, right, top] in pixels of the camera to render to
2024-08-22 13:31:00 -05:00
// Camera viewport is [left,bottom,width,height] in relative values
2024-07-25 17:53:53 -05:00
function camviewport ( )
{
var aspect = ( this . viewport [ 2 ] - this . viewport [ 0 ] ) / ( this . viewport [ 3 ] - this . viewport [ 1 ] ) * window . size . x / window . size . y ;
var raspect = this . size . x / this . size . y ;
var left = this . viewport [ 0 ] * window . size . x ;
var bottom = this . viewport [ 1 ] * window . size . y ;
var usemode = this . mode ;
if ( this . break && this . size . x > window . size . x && this . size . y > window . size . y )
usemode = this . break ;
if ( usemode === "fit" )
if ( raspect < aspect ) usemode = "height" ;
else usemode = "width" ;
switch ( usemode ) {
case "stretch" :
case "expand" :
return [ 0 , 0 , window . size . x , window . size . y ] ;
case "keep" :
return [ left , bottom , left + this . size . x , bottom + this . size . y ] ;
case "height" :
var ret = [ left , 0 , this . size . x * ( window . size . y / this . size . y ) , window . size . y ] ;
ret [ 0 ] = ( window . size . x - ( ret [ 2 ] - ret [ 0 ] ) ) / 2 ;
return ret ;
case "width" :
var ret = [ 0 , bottom , window . size . x , this . size . y * ( window . size . x / this . size . x ) ] ;
ret [ 1 ] = ( window . size . y - ( ret [ 3 ] - ret [ 1 ] ) ) / 2 ;
return ret ;
}
return [ 0 , 0 , window . size . x , window . size . y ] ;
}
// pos is pixels on the screen, lower left[0,0]
function camscreen2world ( pos )
{
var view = this . screen2cam ( pos ) ;
view . x *= this . size . x ;
view . y *= this . size . y ;
view = view . sub ( [ this . size . x / 2 , this . size . y / 2 ] ) ;
view = view . add ( this . pos . xy ) ;
return view ;
}
2024-08-22 13:31:00 -05:00
// three coordinatse
// world coordinates, the "actual" view relative to the game's universe
// camera coordinates, normalized from 0 to 1 inside of a camera's viewport, bottom left is 0,0, top right is 1,1
// screen coordinates, pixels, 0,0 at the bottom left of the window and [w,h] at the top right of the screen
2024-07-25 17:53:53 -05:00
camscreen2world . doc = "Convert a view position for a camera to world."
2024-08-22 13:31:00 -05:00
// return camera coordinates given a screen position
2024-07-25 17:53:53 -05:00
function screen2cam ( pos )
{
var viewport = this . view ( ) ;
2024-08-22 13:31:00 -05:00
var width = viewport [ 2 ] ;
var height = viewport [ 3 ] ;
var viewpos = pos . sub ( [ viewport [ 0 ] , viewport [ 1 ] ] ) ;
return viewpos . div ( [ width , height ] ) ;
}
function camextents ( )
{
var half = this . size ; //.scale(0.5);
return {
l : this . pos . x - half . x ,
r : this . pos . x + half . x ,
t : this . pos . y + half . y ,
b : this . pos . y - half . y
} ;
2024-07-25 17:53:53 -05:00
}
screen2cam . doc = "Convert a screen space position in pixels to a normalized viewport position in a camera."
2024-08-27 14:58:08 -05:00
prosperon . gizmos = function ( )
{
game . all _objects ( o => {
if ( o . gizmo ) render . image ( game . texture ( o . gizmo ) , o . pos ) ;
} ) ;
}
2024-07-25 17:53:53 -05:00
prosperon . make _camera = function ( )
{
var cam = world . spawn ( ) ;
cam . near = 0.1 ;
cam . far = 1000 ;
cam . ortho = true ;
cam . viewport = [ 0 , 0 , 1 , 1 ] ;
cam . size = window . size . slice ( ) ; // The render size of this camera in pixels
// In ortho mode, this determines how many pixels it will see
cam . mode = "stretch" ;
cam . screen2world = camscreen2world ;
cam . screen2cam = screen2cam ;
2024-08-22 13:31:00 -05:00
cam . extents = camextents ;
2024-07-25 17:53:53 -05:00
cam . mousepos = function ( ) { return this . screen2world ( input . mouse . screenpos ( ) ) ; }
cam . view = camviewport ;
cam . offscreen = false ;
return cam ;
}
var screencolor ;
2024-09-03 14:08:46 -05:00
globalThis . imtoggle = function ( name , obj , field ) { obj [ field ] = imgui . checkbox ( name , obj [ field ] ) ; }
var replstr = "" ;
var imdebug = function ( )
{
imtoggle ( "Physics" , debug , 'draw_phys' ) ;
imtoggle ( "Bouning boxes" , debug , 'draw_bb' ) ;
imtoggle ( "Gizmos" , debug , 'draw_gizmos' ) ;
imtoggle ( "Names" , debug , 'draw_names' ) ;
imtoggle ( "Sprite nums" , debug , 'sprite_nums' ) ;
imtoggle ( "Debug overlay" , debug , 'show' ) ;
imtoggle ( "Show ur names" , debug , 'urnames' ) ;
}
var imgui _fn = function ( )
{
render . imgui _new ( window . size . x , window . size . y , 0.01 ) ;
if ( debug . console ) debug . console = imgui . window ( "console" , _ => { imgui . text ( console . transcript ) ; replstr = imgui . textinput ( undefined , replstr ) ; imgui . button ( "submit" , _ => { eval ( replstr ) ; replstr = "" ; } ) ; } ) ;
imgui . mainmenubar ( _ => {
imgui . menu ( "File" , _ => {
imgui . menu ( "Game settings" , _ => {
window . title = imgui . textinput ( "Title" , window . title ) ;
window . icon = imgui . textinput ( "Icon" , window . icon ) ;
imgui . button ( "Refresh window" , _ => {
window . set _icon ( game . texture ( window . icon ) ) ;
} ) ;
} ) ;
imgui . button ( "quit" , os . quit ) ;
} ) ;
imgui . menu ( "Debug" , imdebug ) ;
imgui . menu ( "View" , _ => {
2024-09-04 14:34:45 -05:00
imtoggle ( "Profiler" , debug , 'showprofiler' ) ;
2024-09-03 14:08:46 -05:00
imtoggle ( "Terminal out" , debug , 'termout' ) ;
imtoggle ( "Meta [f7]" , debug , 'meta' ) ;
imtoggle ( "Cheats [f8]" , debug , 'cheat' ) ;
imtoggle ( "Console [f9]" , debug , 'console' ) ;
} ) ;
imgui . sokol _gfx ( ) ;
imgui . menu ( "Graphics" , _ => {
imtoggle ( "Draw sprites" , render , 'draw_sprites' ) ;
imtoggle ( "Draw particles" , render , 'draw_particles' ) ;
imtoggle ( "Draw HUD" , render , 'draw_hud' ) ;
imtoggle ( "Draw GUI" , render , 'draw_gui' ) ;
imtoggle ( "Draw gizmos" , render , 'draw_gizmos' ) ;
imgui . menu ( "Window" , _ => {
window . fullscreen = imgui . checkbox ( "fullscreen" , window . fullscreen ) ;
// window.vsync = imgui.checkbox("vsync", window.vsync);
imgui . menu ( "MSAA" , _ => {
for ( var msaa of gamestate . msaa )
imgui . button ( msaa + "x" , _ => window . sample _count = msaa ) ;
} ) ;
imgui . menu ( "Resolution" , _ => {
for ( var res of gamestate . resolutions )
imgui . button ( res , _ => window . resolution = res ) ;
} ) ;
} ) ;
} ) ;
prosperon . menu _hook ? . ( ) ;
} ) ;
prosperon . imgui ( ) ;
render . imgui _end ( ) ;
}
2024-07-25 17:53:53 -05:00
prosperon . render = function ( )
{
profile . frame ( "world" ) ;
render . set _camera ( prosperon . camera ) ;
profile . frame ( "sprites" ) ;
2024-08-25 14:23:22 -05:00
if ( render . draw _sprites ) render . sprites ( ) ;
if ( render . draw _particles ) draw _emitters ( ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
profile . frame ( "draws" ) ;
prosperon . draw ( ) ;
profile . endframe ( ) ;
prosperon . hudcam . size = prosperon . camera . size ;
prosperon . hudcam . transform . pos = [ prosperon . hudcam . size . x / 2 , prosperon . hudcam . size . y / 2 , - 100 ] ;
render . set _camera ( prosperon . hudcam ) ;
profile . endframe ( ) ;
profile . frame ( "hud" ) ;
2024-08-25 14:23:22 -05:00
if ( render . draw _hud ) prosperon . hud ( ) ;
2024-08-27 14:58:08 -05:00
render . flush _text ( ) ;
render . set _camera ( prosperon . camera ) ;
2024-08-26 11:13:26 -05:00
if ( render . draw _gizmos && prosperon . gizmos ) prosperon . gizmos ( ) ;
2024-07-25 17:53:53 -05:00
render . flush _text ( ) ;
render . end _pass ( ) ;
profile . endframe ( ) ;
2024-08-05 15:26:18 -05:00
profile . endframe ( ) ;
profile . endframe ( ) ;
2024-07-25 17:53:53 -05:00
/* draw the image of the game world first */
render . glue _pass ( ) ;
2024-08-05 15:26:18 -05:00
profile . frame ( "frame" ) ;
profile . frame ( "render" ) ;
profile . frame ( "post process" ) ;
2024-07-25 17:53:53 -05:00
render . viewport ( ... prosperon . camera . view ( ) ) ;
render . use _shader ( render . postshader ) ;
render . use _mat ( { diffuse : prosperon . screencolor } ) ;
render . draw ( shape . quad ) ;
profile . endframe ( ) ;
profile . frame ( "app" ) ;
// Flush & render
prosperon . appcam . transform . pos = [ window . size . x / 2 , window . size . y / 2 , - 100 ] ;
prosperon . appcam . size = window . size . slice ( ) ;
if ( os . sys ( ) !== 'macos' )
prosperon . appcam . size . y *= - 1 ;
render . set _camera ( prosperon . appcam ) ;
render . viewport ( ... prosperon . appcam . view ( ) ) ;
// Call gui functions
mum . style = mum . dbg _style ;
2024-08-25 14:23:22 -05:00
if ( render . draw _gui ) prosperon . gui ( ) ;
2024-07-25 17:53:53 -05:00
if ( mum . drawinput ) mum . drawinput ( ) ;
render . flush _text ( ) ;
mum . style = mum . base ;
2024-09-09 18:55:07 -05:00
check _flush ( ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
profile . frame ( "imgui" ) ;
2024-09-03 14:08:46 -05:00
if ( debug . show )
imgui _fn ( ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
render . end _pass ( ) ;
render . commit ( ) ;
2024-09-06 22:47:04 -05:00
endframe ( ) ;
2024-07-25 17:53:53 -05:00
}
2024-08-02 20:52:50 -05:00
prosperon . process = function process ( ) {
2024-07-25 17:53:53 -05:00
profile . frame ( "frame" ) ;
var dt = profile . secs ( profile . now ( ) ) - frame _t ;
frame _t = profile . secs ( profile . now ( ) ) ;
2024-08-07 16:55:08 -05:00
profile . frame ( "hotreload" ) ;
actor . hotreload ( ) ;
render . hotreload ( ) ;
2024-08-12 15:19:34 -05:00
game . tex _hotreload ( ) ;
2024-08-08 13:25:47 -05:00
repl . hotreload ( ) ;
2024-08-07 16:55:08 -05:00
profile . endframe ( ) ;
2024-08-06 14:23:21 -05:00
/* debugging: check for gc */
profile . print _gc ( ) ;
var cycles = os . check _cycles ( ) ;
if ( cycles ) say ( cycles ) ;
2024-07-25 17:53:53 -05:00
profile . frame ( "app update" ) ;
prosperon . appupdate ( dt ) ;
profile . endframe ( ) ;
profile . frame ( "input" ) ;
input . procdown ( ) ;
profile . endframe ( ) ;
if ( sim . mode === "play" || sim . mode === "step" ) {
profile . frame ( "update" ) ;
prosperon . update ( dt * game . timescale ) ;
2024-08-25 14:23:22 -05:00
update _emitters ( dt * game . timescale ) ;
2024-07-25 17:53:53 -05:00
profile . endframe ( ) ;
if ( sim . mode === "step" ) sim . pause ( ) ;
profile . frame ( "physics" ) ;
physlag += dt ;
while ( physlag > physics . delta ) {
physlag -= physics . delta ;
prosperon . phys2d _step ( physics . delta * game . timescale ) ;
prosperon . physupdate ( physics . delta * game . timescale ) ;
}
profile . endframe ( ) ;
}
profile . frame ( "render" ) ;
prosperon . window _render ( window . size ) ;
prosperon . render ( ) ;
profile . endframe ( ) ;
profile . endframe ( ) ;
}
2024-02-29 13:54:33 -06:00
return { render } ;