From 84e04191c8b1d466996ca47e748cdcb3273ce27b Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 16 Apr 2020 22:16:20 +0200 Subject: [PATCH 1/5] Unittests and demos update -fixed bug in EntityManager -added better support for non-betterC unittests -added many new unittests -slightly improved JUnit xml output -fixed WASM compile script -added new textures -fixed model texture coordinaes in demos -some minor bug fixes in demo TODO: demos cpu usage in non-betterC mode --- demos/assets/textures/apple.png | Bin 0 -> 2402 bytes demos/assets/textures/atlas.png | Bin 0 -> 17825 bytes demos/assets/textures/snake.png | Bin 0 -> 2385 bytes demos/assets/textures/snake_head.png | Bin 0 -> 2517 bytes demos/assets/textures/snake_horizontal.png | Bin 0 -> 2718 bytes demos/compile_wasm.py | 2 +- demos/source/app.d | 3 +- demos/source/demos/snake.d | 25 +- demos/source/demos/space_invaders.d | 27 +- dub.json | 2 - source/ecs/manager.d | 3 + tests/basic.d | 389 ++++++++++++++++++++- tests/runner.d | 53 ++- 13 files changed, 453 insertions(+), 51 deletions(-) create mode 100644 demos/assets/textures/apple.png create mode 100644 demos/assets/textures/atlas.png create mode 100644 demos/assets/textures/snake.png create mode 100644 demos/assets/textures/snake_head.png create mode 100644 demos/assets/textures/snake_horizontal.png diff --git a/demos/assets/textures/apple.png b/demos/assets/textures/apple.png new file mode 100644 index 0000000000000000000000000000000000000000..63d8fb4be09a56b1f63063c0e9a96b263c636418 GIT binary patch literal 2402 zcmV-o37z(dP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+ND=(lJq7F{Ld+J1SDSKI6SLzgB(B2%bwYp-JLHP z*BXpLYSfM7Rqda@yZQ@1Hjb5bL45RH<7cCdoX`=yereuG+j-v)`gESg)%AigWYC)R zD1MJOj5Fr*9xvNY!nk`d6x)80pI@YHh-EuC9=9Vy%Ym-jP}+tJZ_jo;=k3`?36EQ- zX9u!JWc{gevnH^2o`S{QvJSyV^o6wzh+7>%O_=^KM_-@SnaaS#&5+UaE(@hue+hpU zcQPLH@D_cCHwmLFzFL7YK!D}AW83r<&8OI0ti1oJPqww?@I?33+cHouFTTjYw>@sY zu;;IKj;pUP$i1g~a{7QM*vm0LAftB%U+-0VZ)pmImWb3oGqeciA$!0W z%#Ayyff4FEsBQ-MT+f2s#2QfOW|##VOgb+U+0m^nGl@2s=g_V*Mxn0t!;pn<2QXwn zf%aq^dD4M75FwBPf)Z(AV>yEXa*iuNvNbq*fpG}nT47C~IhP%;ab!s_;fyx{+(eT= zmbDK0309z?3!&y2B(#W^cc%;$T^vWss<)gIV)rlCDyuBeGQ?Y%9 z&BjD-naC(U*)I$YfzSQ2H&!Yv9mVxB_dWO<`#Y@a3)pgljb>Yy940&@5g&_NGa8N> z&fX;`wH39u5~2;&#jrg()OdX0&9LL-%G%_}I%X>-Cn$z|0wTOArH!<+$>l-r_mTbv zw7OAWN<7PwDaFJc-|CTc$`z%wHN&+ zWj?gx~dlbhmFa~^h&0(K|k%PsBzRx!=t`@qga zi(S~Wy9&WP%Q&nh5p|E262|ASUDc`Bb|o;y>tqOD;;S2uH&S*VUj;j=8sFbLT+;GG z8dN6_wjIvyQ9>=(6~q|pl}jwhcoM>{n$4s12enmIuf$mC#3#Qb&A26PUg{f7L2{H& zW4c0G59|1JiG}JcN3Kb1{-`ZP9V%T~Y|BqfmjaWy(#1<%`zqmU(dqyMitsL;8FeyI zJ^9_mZhhb|4b3Vl_^14oNjqw4t9chyK=icmANVQW`IMJ96&#y6$BO^7)NiHZODTr! zJgI=p`3C7XKwox$0aqU)|2~qtRk!gQ=6^w{ejx3qc)u)CzX1OjnR*kzj&Iqh{sqIh zSDuxx6Mg^y0flKpLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xFhTr~3MJft*5OK&*6~uz5 zh@)1a2o*xD(5i#UrGL<*AxUv@6kH1q{w!79}p);Cq)-2@w=qZBE~z8 zdwB1AU+%sG{Pi+Z&EPnoYL<~o#Dz?DRS3Nzh+di_7?qf*&xv9Zp5yBtKEB_@c$RnF zpQBsJnGEm=#IsB{EaDB~=}k-LyiXiqMM)t(Cmu8Cg2azpmtB72TyWUWGb2ViHBTHN z77A@Fw=pXkD)AI?R8cj`_h(#IIB#)Q%T?CACx2l$r>!h=oz@@{Si}-U2#`@l31wJ_ z(XNqVB1PwM5C4GU7s(})s{}@l1yrCya{ScGq=>9v*?Jpy{Rfs5;wChq~4J3#-FE*X*|1!(#6dEotwz9|dz z-2z=}Zr_^cIDG)p)T`tTaBv6=7btt(xDGT}XZ)uK)l532;bRa{vGf6951U69E94oEQKA00(qQO+^Rf1P~B3DFG(RfB*mh z8FWQhbVF}#ZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b0YgbdK~y-)rIWu-!ay9y zKi5(UG-xpCWDKTZ;SqcaR%R0u!{TH32yV`n z7mlKydAXzJnX@=<6CSkyczJ%JNx*liw`;J^;>nb~g9I>q{~~Hs`Ak(F_Um}``zZIL zQ1|@Ut<807*qoM6N<$g0EF=?*IS* literal 0 HcmV?d00001 diff --git a/demos/assets/textures/atlas.png b/demos/assets/textures/atlas.png new file mode 100644 index 0000000000000000000000000000000000000000..498f34dd82959385bc9a96199c88707d782b46a0 GIT binary patch literal 17825 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 DhDLD3 literal 0 HcmV?d00001 diff --git a/demos/assets/textures/snake_head.png b/demos/assets/textures/snake_head.png new file mode 100644 index 0000000000000000000000000000000000000000..9c8dbae6bf5094c1ae8bbef837d7a4a55f3b386c GIT binary patch literal 2517 zcmV;`2`cu9P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+ND=plI*As{AU%j1SDQ!IT&!n?BFhc5`?k4s=7~~ zxOUi30;EJK376^r`}Z{e;9^|Hha@q_XmR=MGZ%Ek>Q&~Ote@}o!(N>)aCQHJ}U-pgAw!cDud##W$Ok&zJelwpKWNp?mjM7?`(#moSKZ$=wTk zako=$UI!?Arh9VwK$QG8%wG^WH$3&Yze|rt60y58DA?$bkYI zkwg^9Cgwy0M+yikWQCpQ0}N0I+yIh25)IrS31He_O`>{qP>|() zK>Q>xh@lc(@F9d4Qjm~Ci7tAB42v9I56-NR_dJ*zoY~CCiogIF1~-jtp~&7i--*LXo4cF2zv9hA|08ewTjtE5 z?*C+N@@9H?@b-bVHjeE&8PhBrKD7?nhw(0jrHoUwn5*++3oCz`Vd9^Z{IWH-&Z1UN zuEmxqwSUo?A18pH**ltN|Fb2tRuobZqViG_;#`LS-=JAVU`t+iXnHGae)Z3ZU9@i@ zPCCWj%O9iLM=dD&kxjE#aP&AI$ODp%rJ+MXWE8*ALpmw?15i(uWg+8rPnk|bBsrATnQ#jZ+ zR63>z#UH`1jKl{yOKOIA@9K!lUl@04xA`|9&0XLhlgvly#-$E^;&Y3pT5WB*Gz_ff zd$1}MbrgaFQ8}rMIKO5O$K^$Dv?eBHux#ra1z$vn!oe4c!Y|dn`O`qSLT7ulo3oJZnbi zT{&-aT=3V-hu3_0Eh<+SMSPcNVaqpk3X72|PU((Q`4OHO_=>I?-116ndxu|)E7Ii6 zWj$#grcw+}zT(um-RCSTmShL*yI)75Sam`Hwl-IrQ2R|+T676D-ZkefXLrG2X*(;- z0-5eqtlNjX{_VZ2@)jCC36C{OCBwBwJ+kPE8{AEBT4&=3&IN@it8Zf23rx(rC}&N? zSoi2_o19W$V|^Vm->vzsjpr)kc~=KN0?}xB=&xye#ReUS`OI8Z&kR!=qJOve3EHPE8a?@s?=}4OXU%U+ zJAA>xqvk(qQW`j|t>Wka00D(*LqkwWLqi~Na&Km7Y-Iodc$|HaJxIeq7>3{eNJT0N zb`WvMP!+_2sEDIhp$HX1tFbDh>85?I6% zLkMG0kCh|#W*Vj@N7aS#81;}^*#ldA+qjs;YpLUR1zfAG7vW`1(QO$x_>ju+eh z7y?4OK%-{c-^aGyH~|9Bz?IhWSL(pbC+W487Ci!bwt3>PSS-Q(Sz?S1>VrrEzAj!ts2Uow?P z00006VoOIv09^oG09{CaAg=%b010qNS#tmY3ljhU3ljkVnw%H_000McNlirueSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00I?BL_t(I z%Z-!GPTNorg+Duve+UVVAwZ)_O$7~Ar7rpath=bX?xN4uhv=eDfVyT82}mSL5XdbF z7|WJp`#SdR!i`%akUE?DH|NZmt1}8u#KFNq?K~cjAI(!9Uc7zRkpGhhFgngr9s>Hq z0RWpjYh}{W$zSrrH_GVfg#K`VJDHZu??3Iy6+ompp`X_FZQCFU1OV4(7xae%#hpxf z{`w_FAyHLT!RcAZq7>4$4Mds)@cr8jQ6Ok_^h%vOnacif!1dV$?qrJE?OFJD3I1I| z6bN*qQLTp`cPlV}y=B!%0JP9g>Gmu{nqxaAzL(JI=!i6@+gftZ{!Eb9b}A=~;O57;hf`X)Uc>w+fM^mBlM7@9w=oYpN85tg0@; zjH}ZhwRvdjDgc=%|4SVm=L*2D^UDgn2s1)I zaB^>EX>4U6ba`-PAZ2)IW&i+q+ND=((&Q!#{Ld+J1SH+( z4iwl(E>I+!m=h6z%pj=x#U{7 zIAr5c5RN66QfkGT6*JdpD#lk>8aLN`3oW+Pax1NN$fx@rdhDs^UV0ro+&~A(ihwBemBV~;@Q)^thS%Wnt`88WF zm}GGV#@G`WPm2Kvnipp_llQ!sTb$X#h>E~)GAwQe*-DYUaefkqi*D{7=KhE`6a6oF zuYidM0wNZsS~R0QYSk-XJSJ z{(b!ZnVaVLX;&wbGNq|r*eoq1@wht!>t_+P(U_NLHE9G>#FeTkH2^Lcq4e!ZmTR{-x!*2L6p6tqUo=zB&~IT znA(g_Z>en7ET#8+TW_1jj=lS(RTV0(SX$t{{fDlZnNN`gg9DHg|(K9s$QD#EJXU|rDQ^5M3roRA?0AC0M#@Uh+T5(V&pGcSo3 zB`<3BBY@O3Cv5`+dCFjWLkurpu~#nXA2#+_q}?+R?I$d9O-9jkB;X?7Hr?sjahwW> zrFZse$gm(K#GYzGh%B3O&Y7gmE+J*8Fsd**d7;nw=q47HIxrfe!qRCN# zp|c0S-$hO;I$>conXcCpu{Cfj3ieLJ6-e@pWDb)2U%^8_w4K}^i;DS4j5nh65$mxV z8If^QckLbR`Ie6EuUQt|6nijcD&m+~WN7(`?xWP81|L8#ecVd!DNm{BngzRgp_w&@ z9xy8o4&z4zANTxmj})V9yC!1GW!y0?wpI~3cX(vY8pu?tt}cD%iJ`8^9J_jzL-iAH zBk|4*DIO4SevxXWJDzHT{a>fBkgoBQTplI8cqD+VwI5+XUy{e2M6_a}qLMp4<#ruU zSeG}{R1F_#O$!lTu8J1=o}UtM-TCwJ&)lxybxOj#t|QvX@gDvyh@=V z)yzzE65u-Ll?M{CH00D(*LqkwWLqi~Na&Km7Y-Iodc$|Ha zJxIeq7>3{eNJT0Nb`WvMP!+_2sEDIhp$HX1tFbDh>85?I6%LkMG0kCh|#W*Vj@N7aS#81;}^*#ldA+qjs;YpLUR1zfAG7v zW`1(QO$x_>ju+eh7y?4OK%-{c-^aGyH~|9Bz?IhWSL(pbC+W487Ci!bwt3>PSS-Q(Sz?S1>V zrrEzAj!ts2Uow?P00006VoOIv09^oG09{CaAg=%b010qNS#tmY3ljhU3ljkVnw%H_ z000McNlirueSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2! zfese{00II@L_t(I%YBp0Z<|06#eXa~UfVGSWZXDyl~k3YHc}3`R_gzM^ubcA9ug_7 z)FcH%9LKN_7J9&7qe^|J(R}R8doydW!_~D}+4CWTp~J)*kiJy7z9dr`$CKRtctn>8 zDvwF-O_mF700{nrI8d0D;3-l7cvG8$h5%TNafoD7;>`vC6h%dr763%yb0_cW+C-dQ zoC8z<(>G52YEKXcia1c{qGas!0dT$Jw)owr51d|{BZM#ju;)XfRo!9i^s#yZ*Ovfn z*4zDb_w~fCKR^g$uR$d?08G3Aagb8HmTl3*tLdzE6fVDfHin}fBl`&P_IxjlKl9l< zsg8(_Cs{`+?sU}pby2p$ipBs4{sgVvjNc$Uh&kRqCi=4G^qSX>WBaI6c(_8#vHZ)0y9)_Ve3qm1i1}XPP|IoP0bp z0JMI=-rd2WV0l(xPe#m7-nUbfy25(6x%=moqcFjqjEMuq;H-x(N=!?zeJ;rImp1R= z<_@u3XqF4zo-=@DnT(yIjt0kepRpr5*SK8h?r)U7MpyzNjCKnR)=^3vZc%yM6dM44 Y0VDO}TI_4aMF0Q*07*qoM6N<$f~@!p@Bjb+ literal 0 HcmV?d00001 diff --git a/demos/compile_wasm.py b/demos/compile_wasm.py index c985693..30d0a0f 100644 --- a/demos/compile_wasm.py +++ b/demos/compile_wasm.py @@ -92,7 +92,7 @@ compile(['source'], 'demo.bc') if clean or os.path.exists('../ecs.bc') == 0 or os.path.isfile('../ecs.bc') == 0: compile(['../source'], '../ecs.bc') -emcc_cmd = 'emcc -v ' + shared_flags + emc_flags + '-s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 -s ALLOW_MEMORY_GROWTH=1 -s WASM_MEM_MAX=2048MB -s MALLOC=dlmalloc -s WASM=1 -o index.html ' +emcc_cmd = 'emcc -v ' + shared_flags + emc_flags + '-s ERROR_ON_UNDEFINED_SYMBOLS=0 -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 -s ALLOW_MEMORY_GROWTH=1 -s MINIFY_HTML=0 -s WASM_MEM_MAX=2048MB -s MALLOC=dlmalloc -s WASM=1 -o ecs_demo.html ' #-s ALLOW_MEMORY_GROWTH=1 -s PROXY_TO_PTHREAD=1 -Wl,--no-check-features -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s TOTAL_MEMORY=512MB emcc_cmd += '../ecs.bc ' diff --git a/demos/source/app.d b/demos/source/app.d index ed4817a..6338035 100644 --- a/demos/source/app.d +++ b/demos/source/app.d @@ -138,6 +138,7 @@ struct CountSystem struct EntitiesData { uint length; + const (Entity)[] entity; } bool onBegin() @@ -749,7 +750,7 @@ void loadGFX() GfxConfig.materials = Mallocator.makeArray!Material(1); GfxConfig.meshes = Mallocator.makeArray!Mesh(1); - float[16] vertices = [-0.5,-0.5, 0,0, -0.5,0.5, 0,1, 0.5,-0.5, 1,0, 0.5,0.5, 1,1]; + float[16] vertices = [-0.5,-0.5, 0,1, -0.5,0.5, 0,0, 0.5,-0.5, 1,1, 0.5,0.5, 1,0]; GfxConfig.meshes[0].vertices = Mallocator.makeArray(vertices); ushort[6] indices = [0,1,2,1,2,3]; GfxConfig.meshes[0].indices = Mallocator.makeArray(indices); diff --git a/demos/source/demos/snake.d b/demos/source/demos/snake.d index 2195aaa..f43c5a5 100644 --- a/demos/source/demos/snake.d +++ b/demos/source/demos/snake.d @@ -38,9 +38,7 @@ struct Snake EntityTemplate* apple_tmpl; EntityTemplate* snake_tmpl; - Texture snake_texture; - Texture wall_texture; - Texture apple_texture; + Texture texture; bool move_system = true; bool draw_system = true; @@ -85,15 +83,16 @@ struct Snake void drawMap() { + const float px = 1.0/512.0; foreach(x; 0 .. map_size) { foreach(y; 0 .. map_size) { switch(element(ivec2(x,y)).type) { - case MapElement.Type.apple:launcher.renderer.draw(apple_texture, vec2(x*32,y*32), vec2(32,32), vec4(0,0,1,1), 0, 0 , 0);break; - case MapElement.Type.snake:launcher.renderer.draw(snake_texture, vec2(x*32,y*32), vec2(32,32), vec4(0,0,1,1), 0, 0 , 0);break; - case MapElement.Type.wall:launcher.renderer.draw(wall_texture, vec2(x*32,y*32), vec2(32,32), vec4(0,0,1,1), 0, 0 , 0);break; + case MapElement.Type.apple:launcher.renderer.draw(texture, vec2(x*32,y*32), vec2(32,32), vec4(0,32*px,16*px,16*px), 0, 0 , 0);break; + case MapElement.Type.snake:launcher.renderer.draw(texture, vec2(x*32,y*32), vec2(32,32), vec4(0,48*px,16*px,16*px), 0, 0 , 0);break; + case MapElement.Type.wall:launcher.renderer.draw(texture, vec2(x*32,y*32), vec2(32,32), vec4(0,0,1,1), 0, 0 , 0);break; default:break; } } @@ -444,14 +443,8 @@ void snakeStart() { snake = Mallocator.make!Snake; - snake.snake_texture.create(); - snake.snake_texture.load("assets/textures/buckler.png"); - - snake.apple_texture.create(); - snake.apple_texture.load("assets/textures/buckler.png"); - - snake.wall_texture.create(); - snake.wall_texture.load("assets/textures/buckler.png"); + snake.texture.create(); + snake.texture.load("assets/textures/atlas.png"); launcher.manager.beginRegister(); @@ -503,10 +496,6 @@ void snakeStart() void snakeEnd() { - snake.wall_texture.destroy(); - snake.apple_texture.destroy(); - snake.snake_texture.destroy(); - //launcher.manager.freeTemplate(simple.tmpl); Mallocator.dispose(snake); } diff --git a/demos/source/demos/space_invaders.d b/demos/source/demos/space_invaders.d index 2ded925..5473aed 100644 --- a/demos/source/demos/space_invaders.d +++ b/demos/source/demos/space_invaders.d @@ -29,9 +29,7 @@ struct SpaceInvaders EntityTemplate* enemy_tmpl; EntityTemplate* ship_tmpl; EntityTemplate* laser_tmpl; - Texture enemy_tex; - Texture ship_tex; - Texture laser_tex; + Texture texture; bool move_system = true; bool draw_system = true; @@ -111,6 +109,7 @@ struct CTexture mixin ECS.Component; Texture tex; + vec4 coords = vec4(0,0,0,1); } struct CVelocity @@ -214,7 +213,7 @@ struct DrawSystem { foreach(i; 0..data.length) { - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], vec4(0,0,1,1), 0, 0 , 0); + launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, 0, 0 , 0); //draw(renderer, data.textures[i].tex, data.locations[i], vec2(32,32), vec4(0,0,1,1)); } } @@ -645,13 +644,12 @@ __gshared SpaceInvaders* space_invaders; void spaceInvadersStart() { + const float px = 1.0/512.0; + space_invaders = Mallocator.make!SpaceInvaders; - space_invaders.ship_tex.create(); - space_invaders.ship_tex.load("assets/textures/buckler.png"); - - space_invaders.laser_tex.create(); - space_invaders.laser_tex.load("assets/textures/buckler.png"); + space_invaders.texture.create(); + space_invaders.texture.load("assets/textures/atlas.png"); launcher.manager.beginRegister(); @@ -693,7 +691,8 @@ void spaceInvadersStart() space_invaders.ship_tmpl = launcher.manager.allocateTemplate(components); CTexture* tex_comp = space_invaders.ship_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.ship_tex; + tex_comp.tex = space_invaders.texture;//ship_tex; + tex_comp.coords = vec4(0*px,48*px,16*px,16*px); CLocation* loc_comp = space_invaders.ship_tmpl.getComponent!CLocation; loc_comp.value = vec2(64,64); CLaserWeapon* weapon = space_invaders.ship_tmpl.getComponent!CLaserWeapon; @@ -707,7 +706,8 @@ void spaceInvadersStart() space_invaders.laser_tmpl = launcher.manager.allocateTemplate(components); CTexture* tex_comp = space_invaders.laser_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.laser_tex; + tex_comp.tex = space_invaders.texture;//laser_tex; + tex_comp.coords = vec4(0*px,48*px,16*px,16*px); CScale* scale_comp = space_invaders.laser_tmpl.getComponent!CScale; scale_comp.value = vec2(4,16); CVelocity* vel_comp = space_invaders.laser_tmpl.getComponent!CVelocity; @@ -724,7 +724,8 @@ void spaceInvadersStart() space_invaders.enemy_tmpl = launcher.manager.allocateTemplate(components); CTexture* tex_comp = space_invaders.enemy_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.ship_tex; + tex_comp.tex = space_invaders.texture;//ship_tex; + tex_comp.coords = vec4(32*px,32*px,16*px,16*px); CLocation* loc_comp = space_invaders.enemy_tmpl.getComponent!CLocation; loc_comp.value = vec2(64,space_invaders.map_size.y - 64); CShootDirection* shoot_dir_comp = space_invaders.enemy_tmpl.getComponent!CShootDirection; @@ -775,8 +776,6 @@ void spaceInvadersEnd() launcher.manager.getSystem(MovementSystem.system_id).disable(); launcher.manager.getSystem(ClampPositionSystem.system_id).disable(); - space_invaders.ship_tex.destroy(); - launcher.manager.freeTemplate(space_invaders.enemy_tmpl); Mallocator.dispose(space_invaders); } diff --git a/dub.json b/dub.json index dd0933c..1709ae0 100755 --- a/dub.json +++ b/dub.json @@ -125,7 +125,5 @@ "tests/tests.d" ] } - - ] } \ No newline at end of file diff --git a/source/ecs/manager.d b/source/ecs/manager.d index f6f345a..04b1c31 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -1752,6 +1752,7 @@ export struct EntityManager } add_len++; //move elements after new listener + if(add_len < tmp_add.length) for (int k = add_len; k > j; k--) { tmp_add[k] = tmp_add[k - 1]; @@ -1771,6 +1772,7 @@ export struct EntityManager } rem_len++; //move elements after new listener + if(rem_len < tmp_add.length) for (int k = rem_len; k > j; k--) { tmp_rem[k] = tmp_rem[k - 1]; @@ -1790,6 +1792,7 @@ export struct EntityManager } ch_len++; //move elements after new listener + if(ch_len < tmp_add.length) for (int k = ch_len; k > j; k--) { tmp_ch[k] = tmp_ch[k - 1]; diff --git a/tests/basic.d b/tests/basic.d index c3dfcc5..451f230 100644 --- a/tests/basic.d +++ b/tests/basic.d @@ -1,7 +1,9 @@ module tests.basic; -import ecs.manager; import ecs.core; +import ecs.manager; +import ecs.system; +import ecs.attributes; struct CInt { @@ -57,15 +59,59 @@ struct CUnregistered short value = 12; } +struct LongAddSystem +{ + mixin ECS.System; + + struct EntitiesData + { + int length; + + CLong[] long_; + } + + void onUpdate(EntitiesData data) + { + updates_count++; + foreach(i;0..data.length) + { + data.long_[i] += 1; + } + } + + int updates_count = 0; +} + +struct EmptySystem +{ + mixin ECS.System!16; + + struct EntitiesData + { + int thread_id; + } + + void onUpdate(EntitiesData data) + { + count++; + } + + int count = 0; +} + void beforeEveryTest() { gEM.initialize(1); + gEM.beginRegister(); + gEM.registerComponent!CInt; gEM.registerComponent!CFloat; gEM.registerComponent!CDouble; gEM.registerComponent!CLong; gEM.registerComponent!CShort; + + gEM.endRegister(); } void afterEveryTest() @@ -183,3 +229,344 @@ unittest gEM.freeTemplate(tmpl_6); gEM.freeTemplate(tmpl_7); } + +@("UnsortedComponentIDs") +unittest +{ + //basic template allocation + ushort[2] ids = [CFloat.component_id, CInt.component_id]; + ushort[2] ids2 = [CInt.component_id, CFloat.component_id]; + EntityTemplate* tmpl_ = gEM.allocateTemplate(ids); + EntityTemplate* tmpl_2 = gEM.allocateTemplate(ids2); + assert(tmpl_.info.components.length == 2); + assert(tmpl_.getComponent!CInt); + assert(tmpl_.getComponent!CFloat); + assert(*tmpl_.getComponent!CInt == 1); + assert(*tmpl_.getComponent!CFloat == 2.0); + assert(tmpl_.info == tmpl_2.info); +} + +@("MultiRegister") +unittest +{ + gEM.beginRegister(); + + gEM.endRegister(); + + gEM.beginRegister(); + + gEM.registerComponent!CLong; + gEM.registerComponent!CShort; + + gEM.endRegister(); +} + +@("EmptySystem") +unittest +{ + gEM.beginRegister(); + + gEM.registerSystem!EmptySystem(0); + + gEM.endRegister(); + + EmptySystem* system = gEM.getSystem!EmptySystem; + assert(system !is null); + assert(system.count == 0); + + System* ecs_system = gEM.getSystem(EmptySystem.system_id); + assert(ecs_system !is null); + assert(ecs_system.id == EmptySystem.system_id); + assert(ecs_system.name == "EmptySystem"); + + gEM.begin(); + + gEM.update(); + + gEM.end(); + + assert(system.count == 1); +} + +@("SystemCallbacks") +unittest +{ + struct TestSystem + { + mixin ECS.System!16; + + mixin ECS.ExcludedComponents!(CShort); + + struct EntitiesData + { + int length; + CLong[] long_; + @optional CInt[] int_; + } + + void onCreate() + { + create++; + } + + void onDestroy() + { + (*destroy)++; + } + + void onEnable() + { + enable++; + } + + void onDisable() + { + disable++; + } + + bool onBegin() + { + begin++; + update = 0; + return pass; + } + + void onEnd() + { + end++; + } + + void onUpdate(EntitiesData data) + { + update++; + } + + int create = 0; + int* destroy; + int update = 0; + int begin = 0; + int end = 0; + int enable = 0; + int disable = 0; + bool pass = true; + } + + gEM.beginRegister(); + + gEM.registerSystem!TestSystem(0); + + gEM.endRegister(); + + TestSystem* system = gEM.getSystem!TestSystem; + int destroy = 0; + system.destroy = &destroy; + + gEM.beginRegister(); + + gEM.registerSystem!TestSystem(0); + + gEM.endRegister(); + + system = gEM.getSystem!TestSystem; + system.destroy = &destroy; + assert(system !is null); + assert(system.create == 1); + assert(system.begin == 0); + assert(system.end == 0); + assert(system.enable == 1); + assert(system.disable == 0); + //FIXME: currently destroy is only called with Manager.destory which is bug, but there is no workaround for this by now + //assert(destroy == 1); + + System* ecs_system = gEM.getSystem(system.system_id); + + ecs_system.enable(); + assert(system.enable == 1); + ecs_system.disable(); + ecs_system.disable(); + ecs_system.enable(); + assert(system.enable == 2); + assert(system.disable == 1); + + + ushort[2] ids = [CLong.component_id,CFloat.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + gEM.addEntity(tmpl); + + gEM.begin(); + assert(system.begin == 1); + + gEM.update(); + assert(system.update == 1); + + gEM.end(); + assert(system.end == 1); + + ushort[2] ids2 = [CLong.component_id, CInt.component_id]; + EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2); + scope (exit) gEM.freeTemplate(tmpl2); + gEM.addEntity(tmpl2); + gEM.addEntity(tmpl2); + + gEM.begin(); + assert(system.begin == 2); + + gEM.update(); + assert(system.update == 2);//system is updated number of entity blocks times + + gEM.end(); + assert(system.end == 2); + + ushort[2] ids3 = [CLong.component_id, CShort.component_id]; + EntityTemplate* tmpl3 = gEM.allocateTemplate(ids3); + scope (exit) gEM.freeTemplate(tmpl3); + gEM.addEntity(tmpl3); + + //entity with excluded component shouldn't be updated + gEM.begin(); + assert(system.begin == 3); + + gEM.update(); + assert(system.update == 2); + + gEM.end(); + assert(system.end == 3); + + //system can be disable form update in onBegin() callback, onEnd() callback is called + system.pass = false; + gEM.begin(); + assert(system.begin == 4); + + gEM.update(); + assert(system.update == 0); + + gEM.end(); + assert(system.end == 4); + system.pass = true; + + //disabled system is't called + ecs_system.disable(); + gEM.begin(); + assert(system.begin == 4); + + gEM.update(); + assert(system.update == 0); + + gEM.end(); + assert(system.end == 4); + ecs_system.enable(); +} + +@("CustomPass") +unittest +{ + gEM.beginRegister(); + + gEM.registerPass("custom"); + gEM.registerSystem!LongAddSystem(-1,"custom"); + + gEM.endRegister(); + + LongAddSystem* system = gEM.getSystem!LongAddSystem; + assert(system !is null); + assert(system.updates_count == 0); + + System* ecs_system = gEM.getSystem(LongAddSystem.system_id); + assert(ecs_system !is null); + assert(ecs_system.id == LongAddSystem.system_id); + assert(ecs_system.priority == -1); + assert(ecs_system.name == "LongAddSystem"); + + ushort[1] ids = [CLong.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + gEM.addEntity(tmpl); + + gEM.begin(); + + gEM.update(); + assert(system.updates_count == 0); + gEM.update("custom"); + assert(system.updates_count == 1); + + gEM.end(); +} + + + +@("SystemEntityCallbacks") +unittest +{ + struct TestSystem + { + mixin ECS.System!16; + + mixin ECS.ExcludedComponents!(CShort); + + struct EntitiesData + { + int length; + CLong[] long_; + @optional CInt[] int_; + } + + void onAddEntity(EntitiesData data) + { + add++; + } + + void onRemoveEntity(EntitiesData data) + { + remove++; + } + + void onChangeEntity(EntitiesData data) + { + change++; + } + + void onUpdate(EntitiesData data) + { + } + + int add = 0; + int remove = 0; + int change = 0; + } + + gEM.beginRegister(); + + gEM.registerSystem!TestSystem(0); + + gEM.endRegister(); + + TestSystem* system = gEM.getSystem!TestSystem; + assert(system !is null); + assert(system.add == 0); + assert(system.remove == 0); + assert(system.change == 0); + + ushort[2] ids = [CLong.component_id,CFloat.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + EntityID id0 = gEM.addEntity(tmpl).id; + gEM.commit(); + assert(system.add == 1); + + ushort[2] ids2 = [CLong.component_id, CInt.component_id]; + EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2); + scope (exit) gEM.freeTemplate(tmpl2); + EntityID id1 = gEM.addEntity(tmpl2).id; + gEM.commit(); + assert(system.add == 2); + + ushort[2] ids3 = [CLong.component_id, CShort.component_id]; + EntityTemplate* tmpl3 = gEM.allocateTemplate(ids3); + scope (exit) gEM.freeTemplate(tmpl3); + EntityID id2 = gEM.addEntity(tmpl3).id; + gEM.commit(); + assert(system.add == 2); + + gEM.commit(); +} \ No newline at end of file diff --git a/tests/runner.d b/tests/runner.d index 94b5ed2..9f219bd 100644 --- a/tests/runner.d +++ b/tests/runner.d @@ -60,6 +60,11 @@ string copyString(const char* str) return cast(string) Mallocator.makeArray(arr); } +string copyString(string str) +{ + return cast(string) Mallocator.makeArray((cast(char*)str)[0 .. str.length + 1]); +} + struct TestRunner(Args...) { void generateJUnit() @@ -90,10 +95,10 @@ struct TestRunner(Args...) write(test.name); write("\" classname=\""); write(suite.name); - write("\">\n"); + write("\">"); if (test.msg) { - write("\t\t\t"); write("Assert! File: "); @@ -103,8 +108,10 @@ struct TestRunner(Args...) write(" Message: "); write(test.msg[0 .. $ - 1]); write("\n"); + write("\t\t\n"); } - write("\t\t\n"); + else write("\n"); + } write("\t\n"); @@ -168,21 +175,39 @@ struct TestRunner(Args...) static if (__traits(hasMember, module_, "beforeEveryTest")) module_.beforeEveryTest(); - // Save calling environment for longjmp - int jmp_ret = setjmp(gEnvBuffer); - - if (jmp_ret == ASSERTED) + version(D_BetterC) { - passed = false; - test.passed = false; - test.file = copyString(gAssertInfo.file); - test.file_line = gAssertInfo.line; - test.msg = copyString(gAssertInfo.msg); + // Save calling environment for longjmp + int jmp_ret = setjmp(gEnvBuffer); + + if (jmp_ret == ASSERTED) + { + test.passed = false; + test.file = copyString(gAssertInfo.file); + test.file_line = gAssertInfo.line; + test.msg = copyString(gAssertInfo.msg); + } + else + { + unittest_(); + test.passed = true; + } } else { - unittest_(); - test.passed = true; + import core.exception : AssertError; + try + { + unittest_(); + test.passed = true; + } + catch(AssertError error) + { + test.passed = false; + test.file = copyString(error.file); + test.file_line = cast(int)error.line; + test.msg = copyString(error.msg); + } } if (test.passed) -- 2.47.2 From d0b7138f9f36f0ee957a16d8600c870c9d6982e6 Mon Sep 17 00:00:00 2001 From: Mergul Date: Fri, 17 Apr 2020 17:17:37 +0200 Subject: [PATCH 2/5] More tests: -fixed bug in EntityManger.addComponents -added many new tests --- source/ecs/manager.d | 2 + tests/basic.d | 289 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 288 insertions(+), 3 deletions(-) diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 04b1c31..c3c615c 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -2085,6 +2085,7 @@ export struct EntityManager { num--; new_ids[i] = new_ids[num]; + data_pointers[i] = data_pointers[num]; } } @@ -2558,6 +2559,7 @@ export struct EntityManager pointers[i] = &thread.change_entities_list[index]; index += components[ids[i]].size; } + __addComponents(id, ids, pointers[0 .. num]); } } diff --git a/tests/basic.d b/tests/basic.d index 451f230..f0ab2ef 100644 --- a/tests/basic.d +++ b/tests/basic.d @@ -101,7 +101,7 @@ struct EmptySystem void beforeEveryTest() { - gEM.initialize(1); + gEM.initialize(0); gEM.beginRegister(); @@ -493,11 +493,10 @@ unittest gEM.end(); } - - @("SystemEntityCallbacks") unittest { + //TODO: this test is WIP by now struct TestSystem { mixin ECS.System!16; @@ -569,4 +568,288 @@ unittest assert(system.add == 2); gEM.commit(); +} + +@("TemplateCoverage") +unittest +{ + struct TestSystem + { + mixin ECS.System; + + struct EntitiesData + { + int length; + Entity[] entity; + @readonly CLong[] long_; + @optional CInt[] int_; + @readonly CFloat[] float_; + } + + mixin ECS.ExcludedComponents!(CUnregistered); + + void onUpdate(EntitiesData data) + { + + } + } + + gEM.beginRegister(); + + gEM.registerComponent!CUnregistered; + + gEM.registerSystem!TestSystem(0); + + gEM.endRegister(); +} + +@("UnregisteredSystem") +unittest +{ + struct TestSystem + { + mixin ECS.System; + + struct EntitiesData + { + int length; + Entity[] entity; + @readonly CLong[] long_; + @optional CInt[] int_; + @readonly CFloat[] float_; + } + + void onUpdate(EntitiesData data) + { + + } + } + + assert(gEM.getSystem!TestSystem is null); + assert(gEM.getSystem(TestSystem.system_id) is null); +} + +@("MultithreadedUpdate") +unittest +{ + struct TestSystem + { + mixin ECS.System; + + struct EntitiesData + { + int length; + Entity[] entity; + @readonly CLong[] long_; + @optional CInt[] int_; + @readonly CFloat[] float_; + } + + void onUpdate(EntitiesData data) + { + update++; + entities += data.length; + } + + int update = 0; + int entities = 0; + } + + struct TestEmptySystem + { + mixin ECS.System; + + struct EntitiesData + { + int length; + } + + void onUpdate(EntitiesData data) + { + update++; + } + + int update = 0; + } + + void dispatch(EntityManager.JobGroup grp) + { + foreach(job; grp.jobs) + { + job.execute(); + } + } + + uint getID() + { + return 0; + } + + gEM.setMultithreadingCallbacks(&dispatch, &getID); + + gEM.beginRegister(); + + gEM.registerPass("custom"); + gEM.registerSystem!TestSystem(-1,"custom"); + gEM.registerSystem!TestEmptySystem(1,"custom"); + + gEM.endRegister(); + + TestSystem* system = gEM.getSystem!TestSystem; + TestEmptySystem* empty_system = gEM.getSystem!TestEmptySystem; + + gEM.begin(); + + gEM.updateMT("custom"); + + gEM.end(); + + assert(system.update == 0); + assert(system.entities == 0); + assert(empty_system.update == 1); + + ushort[2] ids = [CLong.component_id,CFloat.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + gEM.addEntity(tmpl); + + gEM.begin(); + + gEM.updateMT("custom"); + + gEM.end(); + + assert(system.update == 1); + assert(system.entities == 1); + assert(empty_system.update == 2); + system.entities = 0; + + foreach(i;0..2000)gEM.addEntity(tmpl); + + gEM.begin(); + + gEM.updateMT("custom"); + + gEM.end(); + + assert(system.update > 2); + assert(system.entities == 2001); + assert(empty_system.update == 3); + system.entities = 0; + + foreach(i;0..10000)gEM.addEntity(tmpl); + + gEM.begin(); + + gEM.updateMT("custom"); + + gEM.end(); + + assert(system.entities == 12001); +} + +unittest +{ + assert(gEM.pageSize == 32768); + assert(gEM.pagesInBlock == 128); +} + +@("AddRemoveEntities") +unittest +{ + ushort[3] ids = [CLong.component_id,CFloat.component_id,CShort.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + + EntityID[5000] entities; + + foreach(i;0..4) + { + foreach(j;0..5000) + { + entities[j] = gEM.addEntity(tmpl).id; + } + gEM.commit(); + foreach(j;0..5000) + { + gEM.removeEntity(entities[j]); + } + gEM.commit(); + } +} + +@("ChangeEntityComponents") +unittest +{ + gEM.beginRegister(); + + gEM.registerComponent!CUnregistered; + + gEM.endRegister(); + + ushort[1] ids = [CLong.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + + EntityID id = gEM.addEntity(tmpl).id; + gEM.commit(); + Entity* entity = gEM.getEntity(id); + assert(entity.id == id); + assert(entity.getComponent!CLong !is null); + assert(entity.getComponent!CFloat is null); + assert(entity.getComponent!CUnregistered is null); + assert(entity.getComponent!CShort is null); + assert(entity.getComponent!CInt is null); + assert(*entity.getComponent!CLong == 10); + + gEM.addComponents(id, CShort(15), CFloat(13)); + gEM.commit(); + + entity = gEM.getEntity(id); + assert(entity.id == id); + assert(entity.getComponent!CLong !is null); + assert(entity.getComponent!CFloat !is null); + assert(entity.getComponent!CUnregistered is null); + assert(entity.getComponent!CShort !is null); + assert(entity.getComponent!CInt is null); + assert(*entity.getComponent!CLong == 10); + assert(*entity.getComponent!CShort == 15); + assert(*entity.getComponent!CFloat == 13); + + ushort[3] ids2 = [CFloat.component_id, CLong.component_id, CUnregistered.component_id]; + gEM.removeComponents(id, ids2); + gEM.commit(); + + entity = gEM.getEntity(id); + assert(entity.id == id); + assert(entity.getComponent!CLong is null); + assert(entity.getComponent!CFloat is null); + assert(entity.getComponent!CUnregistered is null); + assert(entity.getComponent!CShort !is null); + assert(entity.getComponent!CInt is null); + assert(*entity.getComponent!CShort == 15); + + gEM.removeComponents(id, ids2); + gEM.addComponents(id, CShort(11), CLong(2)); //wrong order of components + gEM.commit(); + + entity = gEM.getEntity(id); + assert(entity.id == id); + assert(entity.getComponent!CLong !is null); + assert(entity.getComponent!CFloat is null); + assert(entity.getComponent!CUnregistered is null); + assert(entity.getComponent!CShort !is null); + assert(entity.getComponent!CInt is null); + assert(*entity.getComponent!CLong == 2); + assert(*entity.getComponent!CShort == 15); + + gEM.removeEntity(id); + + entity = gEM.getEntity(id); + assert(entity !is null); + assert(entity.id == id); + + gEM.commit(); + entity = gEM.getEntity(id); + assert(entity is null); } \ No newline at end of file -- 2.47.2 From cb9eaad123d4c79b6e401220f24142763d412144 Mon Sep 17 00:00:00 2001 From: Mergul Date: Sat, 18 Apr 2020 19:16:45 +0200 Subject: [PATCH 3/5] More tests: -removed some unused code -fixed bug with struct destructors (Mallocator called __dtor instead of __xdtor) -added unittests for events -addded _d_eh_personality null implementation as LDC betterC bug workaround --- source/ecs/events.d | 16 +---- source/ecs/manager.d | 5 +- source/ecs/std.d | 6 +- tests/basic.d | 141 ++++++++++++++++++++++++++++++++++++++++++- tests/runner.d | 11 ++++ 5 files changed, 160 insertions(+), 19 deletions(-) diff --git a/source/ecs/events.d b/source/ecs/events.d index 7186d13..317b2f0 100644 --- a/source/ecs/events.d +++ b/source/ecs/events.d @@ -95,7 +95,7 @@ package struct EventManager void clearEvents() nothrow @nogc { - uint threads_count = cast(uint)manager.threads.length; + //uint threads_count = cast(uint)manager.threads.length; foreach(ref event;events) { foreach(ref first_block; event.first_blocks) @@ -133,23 +133,11 @@ package struct EventManager private void disposeData() nothrow @nogc { + clearEvents(); if(events) { foreach(ref event;events) { - foreach(first_block; event.first_blocks) - { - EventBlock* block = first_block; - EventBlock* next_block; - if(block)next_block = first_block.next; - while(block) - { - Mallocator.dispose(block); - block = next_block; - if(block)next_block = block.next; - } - } - Mallocator.dispose(event.blocks); Mallocator.dispose(event.first_blocks); } diff --git a/source/ecs/manager.d b/source/ecs/manager.d index c3c615c..49662dc 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -3138,12 +3138,13 @@ export struct EntityManager struct EntitiesBlock { ///return distance (in bytes) from begin of block to data - export uint dataDelta() nothrow @nogc pure + ///TODO: probably to remove. It's used by old code if I remeber correctly. + /*export uint dataDelta() nothrow @nogc pure { ushort dif = EntitiesBlock.sizeof; alignNum(dif, type_info.alignment); return dif; - } + }*/ ///return pointer to first element in block export void* dataBegin() nothrow @nogc pure diff --git a/source/ecs/std.d b/source/ecs/std.d index a3a4f5e..6077ede 100644 --- a/source/ecs/std.d +++ b/source/ecs/std.d @@ -187,13 +187,15 @@ static struct Mallocator static void dispose(T)(T object) nothrow @nogc { - static if(__traits(hasMember, T, "__dtor"))object.__dtor(); + static if(__traits(hasMember, T, "__xdtor"))object.__xdtor(); + else static if(__traits(hasMember, T, "__dtor"))object.__dtor(); free(cast(void*)object); } static void alignDispose(T)(T object) { - static if(__traits(hasMember, T, "__dtor"))object.__dtor(); + static if(__traits(hasMember, T, "__xdtor"))object.__xdtor(); + else static if(__traits(hasMember, T, "__dtor"))object.__dtor(); version(Posix)free(cast(void*)object); else version(Windows)_aligned_free(cast(void*)object); else version(ECSEmscripten)free(cast(void*)object); diff --git a/tests/basic.d b/tests/basic.d index f0ab2ef..38b5605 100644 --- a/tests/basic.d +++ b/tests/basic.d @@ -311,7 +311,7 @@ unittest void onDestroy() { - (*destroy)++; + if(destroy)(*destroy)++; } void onEnable() @@ -456,6 +456,7 @@ unittest gEM.end(); assert(system.end == 4); ecs_system.enable(); + system.destroy = null; } @("CustomPass") @@ -852,4 +853,142 @@ unittest gEM.commit(); entity = gEM.getEntity(id); assert(entity is null); +} + +@("EventCallbacks") +unittest +{ + struct ETest + { + mixin ECS.Event; + } + + struct ETest2 + { + mixin ECS.Event; + int super_liczba = 0; + } + + struct TestSystem + { + mixin ECS.System; + + struct EntitiesData + { + int length; + Entity[] entity; + @readonly CLong[] long_; + @optional CInt[] int_; + } + + void onUpdate(EntitiesData data) + { + + } + + void handleEvent(Entity* entity, ETest event) + { + CLong* long_ = entity.getComponent!CLong; + CInt* int_ = entity.getComponent!CInt; + *long_ += 16; + if(int_)*int_ += 6; + } + + void handleEvent(Entity* entity, ETest2 event) + { + CLong* long_ = entity.getComponent!CLong; + CInt* int_ = entity.getComponent!CInt; + *long_ += event.super_liczba * 2; + if(int_)*int_ += event.super_liczba * 4; + } + } + + struct TestSystem2 + { + mixin ECS.System; + + struct EntitiesData + { + int length; + Entity[] entity; + CShort[] short_; + @optional CInt[] int_; + } + + void handleEvent(Entity* entity, ETest event) + { + CShort* short_ = entity.getComponent!CShort; + CInt* int_ = entity.getComponent!CInt; + *short_ += 8; + if(int_)*int_ += 2; + } + + void handleEvent(Entity* entity, ETest2 event) + { + CShort* short_ = entity.getComponent!CShort; + CInt* int_ = entity.getComponent!CInt; + *short_ += event.super_liczba; + if(int_)*int_ *= event.super_liczba; + } + } + + gEM.beginRegister(); + + gEM.registerEvent!ETest; + gEM.registerEvent!ETest2; + + gEM.registerSystem!TestSystem2(1); + gEM.registerSystem!TestSystem(0); + + gEM.endRegister(); + + ushort[1] ids = [CLong.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + ushort[1] ids2 = [CShort.component_id]; + EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2); + scope (exit) gEM.freeTemplate(tmpl2); + + Entity* entity = gEM.addEntity(tmpl); + EntityID id = entity.id; + assert(*entity.getComponent!CLong == 10); + Entity* entity2 = gEM.addEntity(tmpl2); + EntityID id2 = entity2.id; + assert(*entity2.getComponent!CShort == 12); + + gEM.sendEvent(id,ETest()); + gEM.sendEvent(id,ETest2(id,10)); + gEM.sendEvent(id2,ETest()); + gEM.sendEvent(id2,ETest2(id2,12)); + gEM.commit(); + + entity = gEM.getEntity(id); + entity2 = gEM.getEntity(id2); + assert(*entity.getComponent!CLong == 46); + assert(*entity2.getComponent!CShort == 32); + + gEM.addComponents(id, CInt(2), CShort(1)); + gEM.sendEvent(id,ETest()); + gEM.sendEvent(id,ETest2(id,2)); + gEM.commit(); + + entity = gEM.getEntity(id); + assert(*entity.getComponent!CLong == 66); + assert(*entity.getComponent!CInt == 36); + + //test for multiple event blocks + long result = *entity.getComponent!CLong; + foreach(i;0..10000) + { + gEM.sendEvent(id,ETest()); + gEM.sendEvent(id,ETest2(id,4)); + result += 16; + result += 8; + } + gEM.commit(); + entity = gEM.getEntity(id); + assert(*entity.getComponent!CLong == result); + + //cover funcion to clearEvents before destroying manager + gEM.sendEvent(id,ETest()); } \ No newline at end of file diff --git a/tests/runner.d b/tests/runner.d index 9f219bd..5eaf99b 100644 --- a/tests/runner.d +++ b/tests/runner.d @@ -385,3 +385,14 @@ extern (C) int main(int argc, char** args) else return 1; } + +version (D_BetterC) +{ + version(LDC) + { + extern (C) __gshared int _d_eh_personality(int, int, size_t, void*, void*) + { + return 0; + } + } +} \ No newline at end of file -- 2.47.2 From f7a1e9bd05fb9640b8e7b2aeb2fa3fd28bdcbd4b Mon Sep 17 00:00:00 2001 From: Mergul Date: Wed, 22 Apr 2020 16:23:42 +0200 Subject: [PATCH 4/5] More test and fixes: -added test for addEntityCopy -test order of onAddEntity, onRemoveEntity, onChangeEntity callbacks calls -testing onAddEntity, onRemoveEntity, onChangeEntity callback -test callEntityFunction call -fixed bug with crashing ECS (setting callers for entity change callbacks) -commented debug asserts conering duplicated components ids (to further consideration) --- source/ecs/manager.d | 23 ++-- tests/basic.d | 249 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 250 insertions(+), 22 deletions(-) diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 49662dc..1b9b959 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -1187,7 +1187,7 @@ export struct EntityManager (cast(Ev*) pointer).onDestroy(); } - info.destroy_callback = &callDestroy; + info.destroy_callback = cast(void function(void*) nothrow @nogc)&callDestroy; } info.size = Ev.sizeof; @@ -1214,7 +1214,7 @@ export struct EntityManager "Can't call function with system which hasn't EntitesData structure."); static assert(__traits(hasMember, Sys, "onUpdate"), "Can't call function with system which hasn't onUpdate function callback."); - static assert(is(T == typeof(&s.onUpdate)), "Function must match system update function."); + static assert(is(SetFunctionAttributes!(T,functionLinkage!(s.onUpdate), functionAttributes!(s.onUpdate)) == typeof(&s.onUpdate)), "Function must match system update function."); static assert(__traits(hasMember, Sys, "system_id"), "Sys must be system type."); System* system = getSystem(Sys.system_id); @@ -1527,8 +1527,8 @@ export struct EntityManager ids[j] = ids[i]; j++; } - else - debug assert(0, "Duplicated components in template!!!"); + //else + // debug assert(0, "Duplicated components in template!!!"); } ids = ids[0 .. j]; } @@ -1544,8 +1544,6 @@ export struct EntityManager { memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp], components[comp].init_data.ptr, components[comp].size); - /*temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size] - = components[comp].init_data;*/ } return temp; @@ -1593,8 +1591,8 @@ export struct EntityManager ids[j] = ids[i]; j++; } - else - debug assert(0, "Duplicated components in template!!!"); + //else + // debug assert(0, "Duplicated components in template!!!"); } ids = ids[0 .. j]; } @@ -1747,7 +1745,7 @@ export struct EntityManager int j; for (j = 0; j < add_len; j++) { - if (systems[i].priority > systems[tmp_add[j]].priority) + if (systems[i].priority < systems[tmp_add[j]].priority) break; } add_len++; @@ -1767,7 +1765,7 @@ export struct EntityManager int j; for (j = 0; j < rem_len; j++) { - if (systems[i].priority > systems[tmp_rem[j]].priority) + if (systems[i].priority < systems[tmp_rem[j]].priority) break; } rem_len++; @@ -1787,7 +1785,7 @@ export struct EntityManager int j; for (j = 0; j < ch_len; j++) { - if (systems[i].priority > systems[tmp_ch[j]].priority) + if (systems[i].priority < systems[tmp_ch[j]].priority) break; } ch_len++; @@ -2727,6 +2725,7 @@ export struct EntityManager call_data); } } + if(events[i].destroy_callback)events[i].destroy_callback(event_pointer); event_pointer += events[i].size; } block = block.next; @@ -2957,7 +2956,7 @@ export struct EntityManager ushort size; ushort alignment; EventCaller[] callers; - void function(void* pointer) destroy_callback; + void function(void* pointer) nothrow @nogc destroy_callback; } /************************************************************************************************************************ diff --git a/tests/basic.d b/tests/basic.d index 38b5605..f3f2832 100644 --- a/tests/basic.d +++ b/tests/basic.d @@ -5,6 +5,8 @@ import ecs.manager; import ecs.system; import ecs.attributes; +import std.array : staticArray; + struct CInt { mixin ECS.Component; @@ -137,6 +139,13 @@ unittest assert(entity.getComponent!CFloat); assert(*entity.getComponent!CInt == 1); assert(*entity.getComponent!CFloat == 2.0); + *entity.getComponent!CInt = 2; + + Entity* entity2 = gEM.addEntityCopy(entity.id); + assert(entity2.getComponent!CInt); + assert(entity2.getComponent!CFloat); + assert(*entity2.getComponent!CInt == 2); + assert(*entity2.getComponent!CFloat == 2.0); } //allocate templates @@ -146,6 +155,8 @@ unittest //basic template allocation ushort[2] ids = [CInt.component_id, CFloat.component_id]; EntityTemplate* tmpl_ = gEM.allocateTemplate(ids); + EntityTemplate* tmpl_d = gEM.allocateTemplate([CFloat.component_id, CInt.component_id, CFloat.component_id].staticArray); + assert(tmpl_d.info == tmpl_.info); assert(tmpl_.info.components.length == 2); assert(tmpl_.getComponent!CInt); assert(tmpl_.getComponent!CFloat); @@ -221,6 +232,7 @@ unittest assert(*tmpl_7.getComponent!CDouble == 3.0); assert(*tmpl_7.getComponent!CLong == 10); + gEM.freeTemplate(tmpl_d); gEM.freeTemplate(tmpl_); gEM.freeTemplate(tmpl_2); gEM.freeTemplate(tmpl_3); @@ -497,7 +509,9 @@ unittest @("SystemEntityCallbacks") unittest { - //TODO: this test is WIP by now + static int add_order = 0; + static int rem_order = 0; + static int change_order = 0; struct TestSystem { mixin ECS.System!16; @@ -514,16 +528,22 @@ unittest void onAddEntity(EntitiesData data) { add++; + assert(add_order == 1); + add_order++; } void onRemoveEntity(EntitiesData data) { remove++; + assert(rem_order == 1); + rem_order++; } void onChangeEntity(EntitiesData data) { change++; + assert(change_order == 1); + change_order++; } void onUpdate(EntitiesData data) @@ -535,9 +555,83 @@ unittest int change = 0; } + struct TestSystem2 + { + mixin ECS.System!16; + + mixin ECS.ExcludedComponents!(CShort); + + struct EntitiesData + { + int length; + CLong[] long_; + @optional CInt[] int_; + } + + void onAddEntity(EntitiesData data) + { + assert(add_order == 2); + add_order = 0; + } + + void onRemoveEntity(EntitiesData data) + { + assert(rem_order == 2); + rem_order = 0 ; + } + + void onChangeEntity(EntitiesData data) + { + assert(change_order == 2); + change_order = 0; + } + + void onUpdate(EntitiesData data) + { + } + } + + struct TestSystem3 + { + mixin ECS.System!16; + + mixin ECS.ExcludedComponents!(CShort); + + struct EntitiesData + { + int length; + CLong[] long_; + @optional CInt[] int_; + } + + void onAddEntity(EntitiesData data) + { + assert(add_order == 0); + add_order++; + } + + void onRemoveEntity(EntitiesData data) + { + assert(rem_order == 0); + rem_order++; + } + + void onChangeEntity(EntitiesData data) + { + assert(change_order == 0); + change_order++; + } + + void onUpdate(EntitiesData data) + { + } + } + gEM.beginRegister(); + gEM.registerSystem!TestSystem3(-1); gEM.registerSystem!TestSystem(0); + gEM.registerSystem!TestSystem2(1); gEM.endRegister(); @@ -547,28 +641,80 @@ unittest assert(system.remove == 0); assert(system.change == 0); - ushort[2] ids = [CLong.component_id,CFloat.component_id]; - EntityTemplate* tmpl = gEM.allocateTemplate(ids); + EntityTemplate* tmpl = gEM.allocateTemplate([CLong.component_id,CFloat.component_id].staticArray); scope (exit) gEM.freeTemplate(tmpl); EntityID id0 = gEM.addEntity(tmpl).id; gEM.commit(); assert(system.add == 1); - ushort[2] ids2 = [CLong.component_id, CInt.component_id]; - EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2); + EntityTemplate* tmpl2 = gEM.allocateTemplate([CLong.component_id, CInt.component_id].staticArray); scope (exit) gEM.freeTemplate(tmpl2); EntityID id1 = gEM.addEntity(tmpl2).id; gEM.commit(); assert(system.add == 2); - ushort[2] ids3 = [CLong.component_id, CShort.component_id]; - EntityTemplate* tmpl3 = gEM.allocateTemplate(ids3); + EntityTemplate* tmpl3 = gEM.allocateTemplate([CLong.component_id, CShort.component_id].staticArray); scope (exit) gEM.freeTemplate(tmpl3); EntityID id2 = gEM.addEntity(tmpl3).id; gEM.commit(); assert(system.add == 2); + gEM.beginRegister(); + gEM.endRegister(); + + gEM.removeComponents(id0, [CFloat.component_id].staticArray); gEM.commit(); + assert(system.add == 2); + assert(system.remove == 0); + assert(system.change == 0); + + gEM.removeComponents(id1, [CInt.component_id].staticArray); + gEM.commit(); + assert(system.add == 2); + assert(system.remove == 0); + assert(system.change == 1); + + gEM.removeComponents(id2, [CShort.component_id].staticArray); + gEM.commit(); + assert(system.add == 3); + assert(system.remove == 0); + assert(system.change == 1); + + gEM.addComponents(id2, CShort(1)); + gEM.commit(); + assert(system.add == 3); + assert(system.remove == 1); + assert(system.change == 1); + + gEM.removeEntity(id0); + gEM.commit(); + assert(system.add == 3); + assert(system.remove == 2); + assert(system.change == 1); + + gEM.addComponents(id1, CInt(1)); + gEM.commit(); + assert(system.add == 3); + assert(system.remove == 2); + assert(system.change == 2); + + gEM.addComponents(id0, CFloat(1)); + gEM.commit(); + assert(system.add == 3); + assert(system.remove == 2); + assert(system.change == 2); + + gEM.removeEntity(id1); + gEM.commit(); + assert(system.add == 3); + assert(system.remove == 3); + assert(system.change == 2); + + gEM.removeEntity(id2); + gEM.commit(); + assert(system.add == 3); + assert(system.remove == 3); + assert(system.change == 2); } @("TemplateCoverage") @@ -699,6 +845,12 @@ unittest TestSystem* system = gEM.getSystem!TestSystem; TestEmptySystem* empty_system = gEM.getSystem!TestEmptySystem; + ushort[2] ids = [CLong.component_id,CFloat.component_id]; + EntityTemplate* tmpl = gEM.allocateTemplate(ids); + scope (exit) gEM.freeTemplate(tmpl); + EntityTemplate* tmpl2 = gEM.allocateTemplate([CLong.component_id,CInt.component_id,CShort.component_id,CFloat.component_id].staticArray); + scope (exit) gEM.freeTemplate(tmpl2); + gEM.begin(); gEM.updateMT("custom"); @@ -709,9 +861,6 @@ unittest assert(system.entities == 0); assert(empty_system.update == 1); - ushort[2] ids = [CLong.component_id,CFloat.component_id]; - EntityTemplate* tmpl = gEM.allocateTemplate(ids); - scope (exit) gEM.freeTemplate(tmpl); gEM.addEntity(tmpl); gEM.begin(); @@ -866,7 +1015,14 @@ unittest struct ETest2 { mixin ECS.Event; + + void onDestroy() + { + destory++; + } + int super_liczba = 0; + static int destory = 0; } struct TestSystem @@ -937,6 +1093,9 @@ unittest gEM.registerEvent!ETest; gEM.registerEvent!ETest2; + gEM.registerEvent!ETest; + gEM.registerEvent!ETest2; + gEM.registerSystem!TestSystem2(1); gEM.registerSystem!TestSystem(0); @@ -961,6 +1120,7 @@ unittest gEM.sendEvent(id2,ETest()); gEM.sendEvent(id2,ETest2(id2,12)); gEM.commit(); + assert(ETest2.destory == 2); entity = gEM.getEntity(id); entity2 = gEM.getEntity(id2); @@ -971,6 +1131,7 @@ unittest gEM.sendEvent(id,ETest()); gEM.sendEvent(id,ETest2(id,2)); gEM.commit(); + assert(ETest2.destory == 3); entity = gEM.getEntity(id); assert(*entity.getComponent!CLong == 66); @@ -986,9 +1147,77 @@ unittest result += 8; } gEM.commit(); + assert(ETest2.destory == 10003); entity = gEM.getEntity(id); assert(*entity.getComponent!CLong == result); //cover funcion to clearEvents before destroying manager gEM.sendEvent(id,ETest()); +} + +@("EntitiesFunction") +unittest +{ + struct TestSystem + { + mixin ECS.System; + + struct EntitiesData + { + uint length; + CInt[] int_; + } + + void onUpdate(EntitiesData entities) + { + + } + } + + void func1(TestSystem.EntitiesData entities) + { + foreach(i;0 .. entities.length) + { + entities.int_[i] += entities.int_[i] / 2; + } + } + + void func2(TestSystem.EntitiesData entities) + { + foreach(i;0 .. entities.length) + { + entities.int_[i] += 8; + } + } + + gEM.beginRegister(); + + gEM.registerSystem!TestSystem(1); + + gEM.endRegister(); + + EntityTemplate* tmpl = gEM.allocateTemplate([CInt.component_id].staticArray); + scope (exit) gEM.freeTemplate(tmpl); + EntityID id1 = gEM.addEntity(tmpl).id; + + EntityTemplate* tmpl2 = gEM.allocateTemplate([CInt.component_id, CLong.component_id].staticArray); + scope (exit) gEM.freeTemplate(tmpl2); + EntityID id2 = gEM.addEntity(tmpl2).id; + + gEM.begin(); + + Entity* entity1 = gEM.getEntity(id1); + Entity* entity2 = gEM.getEntity(id2); + assert(*entity1.getComponent!CInt == 1); + assert(*entity2.getComponent!CInt == 1); + + gEM.callEntitiesFunction!TestSystem(&func2); + assert(*entity1.getComponent!CInt == 9); + assert(*entity2.getComponent!CInt == 9); + + gEM.callEntitiesFunction!TestSystem(&func1); + assert(*entity1.getComponent!CInt == 13); + assert(*entity2.getComponent!CInt == 13); + + gEM.end(); } \ No newline at end of file -- 2.47.2 From 7c263d3ed48b450e2a2a2d3487cb2c75c3b17208 Mon Sep 17 00:00:00 2001 From: Mergul Date: Fri, 24 Apr 2020 20:47:42 +0200 Subject: [PATCH 5/5] SimpleVector test improvement --- tests/vector.d | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/vector.d b/tests/vector.d index 109ff37..4b2ad5b 100644 --- a/tests/vector.d +++ b/tests/vector.d @@ -16,4 +16,20 @@ unittest vector.clear(); assert(vector.length == 0); + + ubyte[1025] array; + foreach(i;0..cast(uint)array.length)array[i] = cast(ubyte)i; + vector.add(array); + assert(vector.length == 1025); + assert(vector[] == array[]); + + SimpleVector vector2; + vector2.clear(); + vector2.add(array[0..1023]); + vector2.add('a'); + vector2.add('b'); + assert(vector2.length == 1025); + assert(vector2[0..1023] == array[0..1023]); + assert(vector2[1023] == 'a'); + assert(vector2[1024] == 'b'); } -- 2.47.2