From 717e04cac5be057beb0fe4199293509f63edcc75 Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Fri, 23 Aug 2013 12:48:34 +0200 Subject: [PATCH 01/40] More icons. At last! --- files/opencs/raster/.directory | 7 +- files/opencs/raster/Info.png | Bin 0 -> 1234 bytes files/opencs/raster/LandTexture.png | Bin 0 -> 2662 bytes files/opencs/raster/PathGrid.png | Bin 0 -> 1297 bytes files/opencs/raster/birthsign.png | Bin 0 -> 2454 bytes files/opencs/raster/body-part.png | Bin 1359 -> 1788 bytes files/opencs/raster/cell.png | Bin 0 -> 1403 bytes files/opencs/raster/class.png | Bin 0 -> 2283 bytes files/opencs/raster/enchantment.png | Bin 0 -> 1812 bytes files/opencs/raster/faction.png | Bin 0 -> 1858 bytes files/opencs/raster/globvar.png | Bin 0 -> 2394 bytes files/opencs/raster/land.png | Bin 0 -> 1220 bytes files/opencs/raster/landpaint.png | Bin 0 -> 1361 bytes files/opencs/raster/magic-effect.png | Bin 0 -> 1702 bytes files/opencs/raster/magicrabbit.png | Bin 0 -> 1820 bytes files/opencs/raster/map.png | Bin 0 -> 1477 bytes files/opencs/raster/race.png | Bin 0 -> 1834 bytes files/opencs/raster/script.png | Bin 0 -> 952 bytes files/opencs/raster/skill.png | Bin 0 -> 1676 bytes files/opencs/raster/spell.png | Bin 0 -> 2071 bytes .../scalable/referenceable-record/.directory | 8 +- .../referenceable-record/activator.svg | 96 +++--------------- 22 files changed, 25 insertions(+), 86 deletions(-) create mode 100644 files/opencs/raster/Info.png create mode 100644 files/opencs/raster/LandTexture.png create mode 100644 files/opencs/raster/PathGrid.png create mode 100644 files/opencs/raster/birthsign.png create mode 100644 files/opencs/raster/cell.png create mode 100644 files/opencs/raster/class.png create mode 100644 files/opencs/raster/enchantment.png create mode 100644 files/opencs/raster/faction.png create mode 100644 files/opencs/raster/globvar.png create mode 100644 files/opencs/raster/land.png create mode 100644 files/opencs/raster/landpaint.png create mode 100644 files/opencs/raster/magic-effect.png create mode 100644 files/opencs/raster/magicrabbit.png create mode 100644 files/opencs/raster/map.png create mode 100644 files/opencs/raster/race.png create mode 100644 files/opencs/raster/script.png create mode 100644 files/opencs/raster/skill.png create mode 100644 files/opencs/raster/spell.png diff --git a/files/opencs/raster/.directory b/files/opencs/raster/.directory index 7a78deef5b..a68c37e302 100644 --- a/files/opencs/raster/.directory +++ b/files/opencs/raster/.directory @@ -1,5 +1,8 @@ [Dolphin] +GroupedSorting=true PreviewsShown=true -Timestamp=2013,3,31,10,12,5 +SortFoldersFirst=false +Timestamp=2013,8,23,12,44,33 Version=3 -ViewMode=1 +ViewMode=2 +VisibleRoles=Compact_text,Compact_size diff --git a/files/opencs/raster/Info.png b/files/opencs/raster/Info.png new file mode 100644 index 0000000000000000000000000000000000000000..d7bdad6cb1699891de65fecd17cd3708daa198bf GIT binary patch literal 1234 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 U5S+aqrvLx|07*qoM6N<$f?VGlaR2}S literal 0 HcmV?d00001 diff --git a/files/opencs/raster/PathGrid.png b/files/opencs/raster/PathGrid.png new file mode 100644 index 0000000000000000000000000000000000000000..23b6b84d74867d65d7eb4542c5bc2864c94ea0ef GIT binary patch literal 1297 zcmV+s1@8KZP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000DlNkl&1h@qpg`~OoL(;U&%JFjqc8IC%f0>1{m%J)=R3diePsZcO~ic( zJjC(Gh?oS(wt-le0Qr`hOXD2F2L^nKfvLq|#8cZZOV1^rOl*(9UIq$g;Pd09KiG~P z{aLDztS^?&5~S=GUMc&-QeJ+kKoLt9;b2+W*WVsG1a3sFLUAY8Nh6Mt{W_vX#Qx5a zBXjrm?}sxoSyCrSf>*&B0_Bno_62$TE;_hfQUZ<79wnV;ebZ7UPfVlz8$>O>XWE0o z10$vid2$}--b8ylWMH*3I0(=+zS3BVzfx;OejrUi|etDWcK!r(4 zA-NVSLON2n_j>n9!Aa*NwN9msj_a&%1UvNsL%JF5+Nn63P#x3bsB&mST z{5%4*azW=LwcKwgfRtSz;6nnJk$^^;z~h3gm{u;O^J0B~>>AvH*9&jKKf4bU>jQlE zle*0OA1@@dE!}qe%ez_m53giai)HlP-rj^>uTL~KG^ltIMF_l)MM%{ycG!>uvJ=Gi z`3pS2Y7goh4NYOm;uwbWWe3`F(hb{=RP?^x5r@OeWL8mzS3z91g>Gw{AgK zXFWD3Cc${U&o3EU*(cFx6xP<(!0-3NmEmDHYqxEDh)@muNY0E#<0ux(lQRxS3JIld<5tk5%-|l62TVre zZy7QYC4lqiXr8d=UauF>cS>DX$6?@gtwuAty@2~W1ZW`5ytz4Gx7jw0t*vRM!pbSQ z%jF{GF(adEevEUipeG*I7Wu5+M1eh&B>F{a7xDw zUAze69*0kGo_#A}wOT(Ya34r#Aj;Q)C_>aHE`9vcUs_Fd zDjF?$fWPT(ARzDWdn{HGx4c=;UA_7m{cWc!f9ChO@0))EwEBWcff-P}00000NkvXX Hu0mjfN03_( literal 0 HcmV?d00001 diff --git a/files/opencs/raster/birthsign.png b/files/opencs/raster/birthsign.png new file mode 100644 index 0000000000000000000000000000000000000000..8192d2ebf86f46bf1a63d47b9e689957c45236c7 GIT binary patch literal 2454 zcmV;H32F9;P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000RENkl`PKUKlt+Rry zlh$s~)sMDEDnr)dY&!*4W7R#oHya$aqS&4N@&0q~d-FWM_xHTd`z8oL(9=eKetvvu zX{q~Zzk5{vW5Hc6mt*uJH9yxuM~7BWbfLgD=ep0k;HF8m3dvzBksw?=6vHnWjOCa2 zDtKvK(INH*iX_R25PU2FXKv1EMQG}W31QXOT(S=MV$Whp<{|9cxfloA3bAh9divQJ z%$HxrJXs&+NIyqq`loU&vl=B1KL|Q;JaZf4H$(zy9{Wq z&%>_gccV7`Gpw(E1>0Ym8#wvm*dDxEya&HszZCDj=ECP^75L_F(*rn%4`^|)Jsao# z?8O_~U8u;OgLswoO9>UH9VHSVpcNK2s0EH|rOMN&)qamf#Q&gcc3z`Bg&+{G~`2wjfK`iehOOYKm82 z{~iynTv6fZAs*JuTLQO!HPoB}e*~3K$6yE1cid-}?tmxi2vQ|4`SoG*2Q>muk48{% zw6-R3L?^89($$H4xO84`!6WaK&ef@Td9`w`r6Y=)(bMHc8r^ELo!atgT zf|u@4@T?sQuC-gqb@V8?u1itetWV^e)b4X1|Kf{lSD$(BN#FqyP9$kGN6JmoM)5Mb zV?xV@8MPORPN7)zA&SDzz#X$09>FQRTDc1U9R3+Hq)Q;9QU(;1wT)@<@o*+YKpA3l z(7=}x`ODx9KQm@B4&h!{_?r;Nt46+~2##0}ZVvwx_2tFL<{b#AJ%h6g5v1X|g3PF$ zuoI3Z%6Q2oH29^outrowoJX1DFK~;FLCtfH$ho%LYHAl0!6y(WI*Yw~cBB0@4O+Ka zAbRdMw8E2aODWSpJhcpVaz7H;D-gjpbdT$Vqc50pX+k}X>QLv9Rn!#l_EGR$(E&)g z#$Gx{B4uyGEY=Mq%1&Tm`%P2VG?Gc>#J|>?r8@+rx(oN4}XUjHR z{G7BIFd!(ef zm+tqTNVe%{1UspL7MhkJE+taEir_3?W@f5u(J?&sAd+TEJt~*b$8s|WS#EU4|Kuf>{!l8anS8Iki=X0z&vNlo=tU(mEA_PBO~~A zq_bMb1eZE}TL9cNtr^MBZoPBNjkKayTb@opPXe2fT!}-Vtb1nD_r?V zn9>0KM`c7`u-@&a=)8dm1wa-Rct?}*TOLh~`$@Msf`8(VXnsM=hfFUjuEg4rgZWx%s7qUq=$=ks^Z| z2e<0~14_s5w#1@bR~-_lgL>C4OQk>QuaX= z>F$pr?Y;D!(=C=Us1p^!nXm}WYv<$0K{NhvEE0e03ZYLOhf4io=$~DQsOipIB9``& zFjyT}znLg0$um559LqRnhm10Jt2nM~7xzU@ zF8A|1&-eNMZeRdlOm;;}IpwKpp*1^6ZZV`Od-Bu5da@EE7Jq$okX0??m|_*&1K-V< z@y%q<8Snc^;SwI}%$?dTz~csdepHXo4^Lv~K@A4mj2OIs3?J_s@uqnv*7WlzJI?!i@xSU>@#T4X3T;#z^!On1(dAT^?vR+Lpy(Rb}d?~b6~2@MQKhH z?K~q+gtu2WV5LroKQ9$PEB8G=Z3064-LFH_><-9t!;(4)2gUNyC5M{I2`$&LhnW z-oL+5W}Ep)_?usU#@2KNs6U=DS*$XD7lkUw)f5-%)pvTU4!0}Q@!N?^m=7((l^u!5 zRDb&oh<)cg68p@i-<)*(hBQ^*NAvLs;jbH3qrPYnbaJ1Ji3DV60=^Ak&F-ivjK!;l z^>}@88(y5wr{Nuk^ysKcM#tgBuo#!4vnCUV*Qns*@?#q#GQ?Yd<7hrUwCF{8$7HzvVFz<}Py^3hu-4Tg9W#MSwpMV63tA(Kwu#E)Xcdcwfc-_`mLs*>>VK-^d1w@X!M-5!Q`F(n{c;(u-W zaJveoQoN|k!0YoH(bZ6Z=e1erG^SD4Qar28p(0<0?#9h% zu1K6R+_Wu}5-{JwND2?I_TN1=E}X<3ALdKLpPyQRXD8BOJ-(ENKdnxM<)|J{4kzPr zRU)1m)2V`SQMXPxVeG@s3H)Y}9Dng4E*1v$O0~RiJ@AEd0ypi~)9xpOKROt1a~>Ax zg2v6NFJ?X#eq)OiaUy36BR@s*;SM8TH9?DV!=(Z2foWxF?6L|9m0d#`77KU2lW$taMp!fX0 zz|R#bp%%JgMTDo#c}%b~E^U<3g&PZRTE~ZuKgYtLen=LXs;iQE>?}er8UIcv5Ds~t5W3Y@Wnr=fy|j%QmDIU%;yAD3~00000NkvXXu0mjfRJ%wu delta 1252 zcmVjNHRL`KTaA0#JC0a)(<=vGx21XjBX~#~xvQ@LMEAg_JIlBQ6=US=It!Hbz4m&eOT!;$B#^?iVj5Q+ROc(*Ui6DiaW38Y?}8taB=C>dZ!b zn2%imJZei)uszvAX05?mUm4bVukXfgcK)j4OT^g&Kz}B7*WN8mCe3fgh10=o?9{nA zcC+(^woJrn6`(tT>vX*GT(Hc+nsFRDg403Dr0)wp!PaCunS0>A*v-ygHm4&tQ~{}g zH{1SoEIjz!N!tJfDw1mQE@E?{g>62axn=BT=W|V|1i%~7fy~B>hD*??B=a@_AX~0_ zvgH~n-hWSI?*6Q}W$b3>vyGP!tC1r=DFkzm(-7|CVJm=B)pX_?V~@$))vUN>>}KaL z8d6w*``M9r+5EZf02mR!X{DzKZ$}ykfG;a<8N1o}^ur_s$%L3`_zZJRmkEH_HVODK zBI8O=3D$?|QI(}<#cAx+ITfeQsd!s)G-5&+%zw9hK}L{@Fr~;g0F20WV7a@HETH=b ziuYF;P?4sERw+g+fmr&b0F(C&@Rzz-buS!x3`3NXk)>Y?@n-Pe9_KeRA`rj`5#cLA zMQSM2Qa9H5LTeVrs?I_q7fjjY6hx?*`DJ4%R(o&l#-14)z!q+*?jj~@4ahj>i*&t; z6@Q2O#pNRz|@(8*Bw{cwwq&rem9O4FHZ^F z_^YyuD< z6Pl>_>y9gI;iz*ePGk2L@^)uVom26_vLL7>E>;~utNs;xi(QB5ZZ|!-wnv;6E>X*{ zg|ifYa>Wl~-U+L2LaP860k5jPRFB1<^LCwEw%tkhya@tQEHkfW9OX@N(0meK1|0jM3X?_Qg(}4;1;KIF5ma z;V0P~fPT>V#PM;uWd0&I-4L0(xo~Fj{(KdR;=Blet9=0Y9H(kpxP{hCHU-*tOYz=3 z1qx$4q49FD4}gewvb-@X2n)>_7+oSq?p^WUbL1#EFR>p0T`WFgm+c!#z6Xj|CU`<6 z;{HoZYnKkNWpw8{27B>yltO2tQpjZ=g@9`ma-ANKr<~!RbUcbUefK|iFCsaz41%&#EP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000E)Nkl7ip7{|GL!GmU5b~|71 zeC^K8$L{QOXFp3zmqMYiu=Go@g;L`@FOuHDjH)v=)sFe z4hB6m#xy35AsiGnXkz}(3@&!t?Z=h_G2t+mndfqGJ|?%3PQ$c7~+MY{LSG$>qfDB1nq+aBecO$Ys8j zhcqNXPVhMQWj`iA?ZWYEotXGw3--K{fnMNmc-He7azz`{pdHr0#o5p2i&%6E{!N}u zy_N#sO75^aoAZ*r_f}E-UM4MfMIV4h?^7bvI&0=rj2Y((*eg?5AxECxZ66uQsHQLWsAZ<|uF zX;OjMN|3pf0Xx8gHmET2Dr#y4{ zt9^*INxpJ^nD>+EWD|Cs*8Ohpsl?H2hLMgvj(mxreAZY1SBeCY(Fn{b^DewIh(LP) z0Xu-O7@DbyxF;ZAlGSXNJnO^LqQA$=VdcN%VgPJ{!md-g-*ARbA*qJYF)S{CZ#t#G z=;k5h8E_T_AszzJ*Mru=po}n@pmR$B#V)^Qs{U#2GyjIQ38kx>yaOnuwznd2%b4A!7jVUG`b!}BnZtF zpgipsw~qzsWWW&mSAVi43c_@AQM@^LE{XAvGB|WKjf3yoXfHAt&>lgCf2{5~pWATr zEBD~3aS_Qw0^$dGzj6;QmKd-)eUnk>Y2SglN5bxuD)v^%={u9~$7|=Hh;51D!mH`jKxkASxr_cE#vUXg%mkkQIlj5gkBA6NVdw-j7|fI4xd~a z+>n53usez?Y7234qjJqr^D2+;;UT(U!CD!3RRXF>(JWVq<~XN$NQ5~kK(bj!Y-a23 z@pAu+%l;ECwSa816)Ckk@O?S3Tvd&Hzb^+G0WB8$P{0Fs;2$t|&*3H>@<{*y002ov JPDHLkV1m1kiJ|}i literal 0 HcmV?d00001 diff --git a/files/opencs/raster/class.png b/files/opencs/raster/class.png new file mode 100644 index 0000000000000000000000000000000000000000..316380363ae0a1039bbd8810b2a100099503446c GIT binary patch literal 2283 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000PDNklh8OL{=Oonk%Cu3ta z&NQ7g9>@*LF1yQKz}^=N?807LdvL3}$gw~WSP)zg1QZkm!sS6~L@-H}ai|c}z{Do8 zwpeY^G#;&!F;#0@J8_(Uzx@(+LX=8OX1X)q%sb!l{Ql4JKF_-p0F?jd^~~^Jy!P6Q zB9Yo7j8l2M>t}W1dkK(96GH`j$%s@Ee_?blQvuot^KXyL$p19q*#G^*DCzI*Nvd!*II?QCivokx=u1&yy>bD`Hs! zydhS|b$9#vCYOX)R`$Z>+K-~5y@+Ou?k+bi%Mu_K#rHMT_oJ!lFbw)^7!BEQIz2wm zv$D1$US)zzmIAxI270{%^hjRca-y&-0YuLKk}2?hn69JFU!Qr7$a@YlOqsa*z6V9y zoP=Wl@f>f~=cBhShg^GqMTHK0+Np;$MglfVhVh=~pq5bQ|Cfj*1sD@vxj1+FdCb1| zQ^;jnBxq7`d$JClwFRgww8LT3W87oHvHBEjvFK1%kdFOTHvG0d2`r`vv4Q{^Up_%@L`t?%ZBn)h}8X<~e1X~Y7q-5hnF9mAx%eR&# zz@n!Xo*Z0>3zMtCu z_BE_RjdLYrvDCuvig+vnMB&XoxI}@;E(CY)?XTe-cM;uw8!U|zfdL_4(-}BctMhq& zuv7wiSQs{L2tY8;?1Kl{#}JS@1d)t}BYP+i3#hYC72veLbmRUU1(LM1MR0b@-@t0R z4yJ1wQR>YI5063=lZ!|i6CojVgbOnfYCW_F9+-I)0cl6Th!tYEl>&|Qr5jHdkoEH~ zt4rvRYLX!#@-9wufmby8HN4>}qUtV#UOk7%%JZO=okK*)48jZFN7&Y1KM}skIE1j6 z1oZEsz!1Osu{v0k0<}`{Sw(p{jvqgcv9U3XjErDlU;qUL1z_`pU~K<*S#Y+l0@2Z2 zu%jZupoM`E5sbL#KnPd?knw3-z8wXh0JT#7kHNt~OiWBHf_HUwp{=bAwQe_Pw8*D= z&gO~8#Eu~iNUkB0PkF8O@p`q!c4M{vAsio>E-81yL*>~t02PEgD4@ z7EJLW5cAf9&s_JJMa5K56miT;UgLZA>_KyLGcn^Eh|`T5?d|Qv{BMH8;Xqzq9_%(7 z(utixkE9WmPk*f7qM}$ttxz#N?T3kzemF7ehcfZU^{Q3ambeOyZa>tP`Jvq5 z2R?f(VxxjCQSwveQ$vk8sCVda=Aaunwlug)^H5S!Lc)u4%}6uoaI~!mJF~?o)N`Oo z(2`BYyU!Q4n$etrI%f*HsxxqMa0k*&DHzyYhU}0HC>KVczqJzCnI??261Giz?8+6w zETK(N@=VgHe}B}Do2TnhQ|ZFo+#K==j~6`8&B?*Nd-sS*=fq@_4rg1m&}sDu(0BUa z81HF&wI&kP%tRDdMs~Ob_=cozL<(U%yxuA!Zk#B^Uyc>x%18mS6Qg0*urSlE z$0r>rB)rcN114XEP09Nf!Pjd#uuf7-G%E$(YqR6}IAP~)C(ie0!z5$ijr17&uFFJv z{!wcJ8m$}%8Jl?IHe6^3N#dxBe>k|AgkK)c#>F=+xX^9(!DpJ3NQ(8xuF6$V#fL&5 zqJu4r0V75TjvxYZWe`eoe*(RnM#ATh5O#*LFxQv42tHXSgMuC4JD~Ukn3e2MIWPSF z$3503!m||Nj}nBh-YLm>0X?1-WN+{BP|#IRL5G`yM%N114KF|y_xc@&LGWlPIN|yI zBwnEJ-_xR5V3aXJwL;qb4tp$yT{5!Zyx|f@ZMr6;`;#FP^Qi_Ak2)sgQD^0GYo??z zYo=nNsk3}Gb&SWN8ockwxM4gwC-hotfe6E;UOOUGnORVC1LwaDUzCDx4+sf6h?lQn zICIrBr|6qpE$4{+-FGCcAYR@#b{2B})N%YQpda$he*taD)yj+Zn<@YR002ovPDHLk FV1mysJKq2R literal 0 HcmV?d00001 diff --git a/files/opencs/raster/enchantment.png b/files/opencs/raster/enchantment.png new file mode 100644 index 0000000000000000000000000000000000000000..c90fb27ce33fbca5c4a6a10ff2c6f3c265d7ca5f GIT binary patch literal 1812 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 Tq^~E300000NkvXXu0mjf43Bmj literal 0 HcmV?d00001 diff --git a/files/opencs/raster/magic-effect.png b/files/opencs/raster/magic-effect.png new file mode 100644 index 0000000000000000000000000000000000000000..e672ffccb3bc9f8203a7a0ebf8954ab17b5ffbf9 GIT binary patch literal 1702 zcmZ8ic~}x=7^gXPNw_VK%L#WbBqAs(P&9!&^DO>AYJX|*W~@1<#L z&C!-tT$8_xnA+-}^pa&Itqzq@<|?002O6 z4_7}~)cwo8P>^|CN{Uz(w&DC>&HzUL-g#N_c{J1;3INm>0;S>dvV8klk6;`C0NnYP zZ5x_Om&y(`@oqu*lZjDyVt5h;a3UO=fQKO5{B;TD5KG7rQ&VwL6#$^126u(}2f^r+ z^IoGE)kmAP^id}&=oA~>b`29zLpAX+1@~fN3?~9nha>9=?rK*{OC1feS^k z>%wO7xm8{um)@%p7!&E&UAX~ z6wx=K=m0aeeahppLkp-kVlUA$h69Um8H{830-1$9vdoKIrpXPOj)YI*wEC$wn zU?NfTU78@f%i!uOa&Ti-1SXFPh; zw0vfNpv%ac_L93+s5RV+&#+HJu?yi$4L$Ae4VLUNyB&`tg>`gZ$WsW3`NhG;F5B zP42M8pw+p!rD5i<{yifvXrWSI<}jJEuAoA2$g>bqB74r|+x(kC>~we&MeK^OXy3 z4^$JYEpTLOEmpQ?%Ww8{A^0|{kzK3v0ohH3hB|n>kBXy8vALiIj(8*lFS5oF zJj;ZkFFji}YRrX(xM_#Y44Li_&6uhjE6cjM6-`=}0jG~J{zIIl>5Ns$J{-&W=XL1% zZ0m9pe?#M=P8ANvhzc~y)4rs@=eZ>mvp0Jfc6o`t!ErgOt#W4tKV49##hknt;z$g0 z_3zIZzdi-oXnb}PB<$O7?q%J6hO-3o>mK*p94%Mw==@Iy881ZLgB6f77yrxG`Y??*QTg)Z(?NnJu8v%-VzlgAlqUcgbz| zbP=^>VVt(?<^1W0@KQHkzi$AzSCi~k%BhUtJNir8$z)>uu=+~p;E5eYDiy)Jkg)s9 zxogjW{2fz?tjTd&G0E4RKa_DG7ts;#8?7W0ZqBXe!i4;}R%JMaPI4J7weD^E|P&)ZsYZ6Hhl6ffGOrUfNQB)-05It;n!pw>5RJ_)UXo$rH}LqmmXCKcE?uZoI2I4`JOu6(@gi5lW~7P0-&JNe&M0`}?MzXb>{;=| oB_i_=g4g@-x5<4v2-u?2mQo5pLDlek**5}!yCGZ|&SBsE3EgiyE&u=k literal 0 HcmV?d00001 diff --git a/files/opencs/raster/magicrabbit.png b/files/opencs/raster/magicrabbit.png new file mode 100644 index 0000000000000000000000000000000000000000..d1d7c8270b2fec8dd98806f591bf5bf4aa70331d GIT binary patch literal 1820 zcmV+%2jlpOP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000JyNklC^@s{=4Ko|d>FYoIl8d~R<2l~J9zLQu3x_n zoleIDl<%zqywTZ)2D$(h<>koJYFox`p0jFIOWCenc=6%|Dk>`YQIo1`(nGvi(UvX7 zVFFtU3;Fk`ch{|3XJi6KqmkS6#{KaKnM{Di*VosFlP6DN*Up`9WLQ;Ig=0sL;?}KO zNK&bOdhZork*&ze>Suv%-n<$4Yt}TX)oOiaW~N@F(KMD*Ypz_rjD-03zy3?4?_2@i zfPCO~XJ;pRdV28c)hiK$gM%0t7(iE77al%*h>ucJZv+FOs183dRAv= zXAiu7{TgLuWvH*O7lM2K{5k5*oDpq#_Usw*^YdT2xw=-nxw&ci-HFJ&L4d#%GMP+A z(c&$a_k;uoBPuEi2?+_PIduw$Xw=vf8fYp`pFWM++FJ3O*Y@w<4;ErbNC6_xn3x!ly`sOrA2b01kT%6< z#l^y$_&2X@Sic@kO-+bcv+1`-TrSACy0{EFIXOLba&%liV#O>NnU_~v zRAeMbPy#rPz{11B5fl^zsZPefvlRGhXJ;qY_-b!&4+jSa zy#-}pWblZHh!Jq^A-^*rN6nHQR&(p&Lvu4c_;M1p1hoz+@ z3Tgh?Y%2HcK{-tVS0yhm4?DJR$F{9oap1rK(3v1IWMB@?lnJ=IyN?2&GiMGQ?CrZO zNa=~B*gqMRGv_P!J}fLu2#9;g!n=3x9`^0qhpHn-(A(Q9=AK)@m3Z{%k+{Ei?_N|^ zRth&HqY`E3_qp%ItP>6ZwapTBRtN#&mbTp{40@#k* zAQ6J=q^#>GMtQ-wPMEoD?a-mhI;5#`5EGG%(4c4p_yuEuGK};=Gfkr6V6E_Yxw^Q+ zTe<);PbGY$!3dB?BSevcbGpj?6V*?CT&Q6xeq_;jA%I4fx08VqxP$((0%b6 zPV8<&b!jWU-u3`r7LhhK-p1~NX6)27VMq22lw|&b!eu{WL+TZ1BYJ-?a_u1Pq94};di+k-~h!DHO-gK=9xf;8}W1_g#7A}k(DA~O&hxg6@0 z?I>RTJqojHu|ZvfwV&vazw}#ZQ%*qj!6qtqDgu4t2{;rITSxG?kq!)Iw}1{MgG!}> zzrVk5MIK2O8hg42_1#|)jzA^p!Z(t7zmP>X;&iNbHW~(J|FE^OF`odP4~BSB{=dQb zfZ?-&3Gi&Q_;|kAY=&)iEcoo%vteUxZ9V~VNJDIF>`3Ns3(jsz_G>-?@&v=;#fwGR z-vxZej2Ub|<`eKF0{kKJuHe(AO=A}{pMZzEyKxbnfN#@tE<0z=;8Ukg^HL7Y3%_;y|tB9;zVD>eE)AGZZSMjInD?G0000< KMNUMnLSTXwuTk3o literal 0 HcmV?d00001 diff --git a/files/opencs/raster/map.png b/files/opencs/raster/map.png new file mode 100644 index 0000000000000000000000000000000000000000..3653797cca076d1ef7a1983d109e67e2fc4ab52c GIT binary patch literal 1477 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 literal 0 HcmV?d00001 diff --git a/files/opencs/raster/script.png b/files/opencs/raster/script.png new file mode 100644 index 0000000000000000000000000000000000000000..297da40210490e4345d2ef8adda136cc8a404db4 GIT binary patch literal 952 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 B*sA~l literal 0 HcmV?d00001 diff --git a/files/opencs/scalable/referenceable-record/.directory b/files/opencs/scalable/referenceable-record/.directory index e2d80ed58c..c633c38a9a 100644 --- a/files/opencs/scalable/referenceable-record/.directory +++ b/files/opencs/scalable/referenceable-record/.directory @@ -1,5 +1,7 @@ [Dolphin] -PreviewsShown=true -Timestamp=2013,3,21,10,19,49 +GroupedSorting=true +SortFoldersFirst=false +Timestamp=2013,8,11,16,50,43 Version=3 -ViewMode=1 +ViewMode=2 +VisibleRoles=Compact_text,Compact_size diff --git a/files/opencs/scalable/referenceable-record/activator.svg b/files/opencs/scalable/referenceable-record/activator.svg index 0c6db59a7d..e917d93327 100644 --- a/files/opencs/scalable/referenceable-record/activator.svg +++ b/files/opencs/scalable/referenceable-record/activator.svg @@ -23,18 +23,18 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="5.6568542" - inkscape:cx="5.7818736" - inkscape:cy="23.778975" + inkscape:zoom="2" + inkscape:cx="-35.165989" + inkscape:cy="-65.142411" inkscape:document-units="px" - inkscape:current-layer="g3891" + inkscape:current-layer="g3910" showgrid="false" showguides="true" inkscape:guide-bbox="true" inkscape:window-width="1280" - inkscape:window-height="994" + inkscape:window-height="1001" inkscape:window-x="0" - inkscape:window-y="30" + inkscape:window-y="23" inkscape:window-maximized="1" inkscape:snap-page="true" inkscape:snap-bbox="true" @@ -45,7 +45,7 @@ inkscape:object-paths="true" inkscape:snap-intersection-paths="false" inkscape:object-nodes="true" - inkscape:snap-global="true" + inkscape:snap-global="false" inkscape:snap-smooth-nodes="true" inkscape:snap-grids="false" inkscape:snap-nodes="true" /> @@ -867,7 +867,7 @@ xlink:href="#linearGradient3942" id="linearGradient3955" gradientUnits="userSpaceOnUse" - gradientTransform="translate(-183.1468,-158.28118)" + gradientTransform="translate(-445.4059,-219.9852)" x1="74.006111" y1="153.75172" x2="344.5" @@ -877,7 +877,7 @@ xlink:href="#linearGradient3880" id="radialGradient3957" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,1.0000234,0,-0.00345228)" + gradientTransform="matrix(0.90336573,0,0,0.90338687,22.936413,14.223841)" cx="237.35278" cy="147.22479" fx="237.35278" @@ -888,7 +888,7 @@ xlink:href="#linearGradient3846" id="radialGradient3959" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.43641683,0,0,0.43645606,205.85223,33.676924)" + gradientTransform="matrix(0.40004875,0,0,0.40008471,208.47728,43.13925)" cx="72.191498" cy="260.15875" fx="72.191498" @@ -1003,84 +1003,18 @@ - - - - - - - - - - - - - - - - + transform="matrix(10.683152,0,0,10.683152,-3645.2454,641.29516)"> - - - From d1516792ce28001bf1a316382e10dc9603e2aab2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 17:17:22 +0200 Subject: [PATCH 02/40] made document data available to filter parser --- apps/opencs/model/filter/parser.cpp | 3 ++- apps/opencs/model/filter/parser.hpp | 8 +++++++- apps/opencs/view/filter/editwidget.cpp | 4 ++-- apps/opencs/view/filter/editwidget.hpp | 7 ++++++- apps/opencs/view/filter/filterbox.cpp | 4 ++-- apps/opencs/view/filter/filterbox.hpp | 7 ++++++- apps/opencs/view/filter/recordfilterbox.cpp | 4 ++-- apps/opencs/view/filter/recordfilterbox.hpp | 7 ++++++- apps/opencs/view/world/tablesubview.cpp | 2 +- 9 files changed, 34 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 5e580b6e15..2cf882f2df 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -506,7 +506,8 @@ void CSMFilter::Parser::error() mError = true; } -CSMFilter::Parser::Parser() : mIndex (0), mError (false) {} +CSMFilter::Parser::Parser (const CSMWorld::Data& data) +: mIndex (0), mError (false), mData (data) {} bool CSMFilter::Parser::parse (const std::string& filter) { diff --git a/apps/opencs/model/filter/parser.hpp b/apps/opencs/model/filter/parser.hpp index 1600992b72..c26168611d 100644 --- a/apps/opencs/model/filter/parser.hpp +++ b/apps/opencs/model/filter/parser.hpp @@ -5,6 +5,11 @@ #include "node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSMFilter { struct Token; @@ -15,6 +20,7 @@ namespace CSMFilter std::string mInput; int mIndex; bool mError; + const CSMWorld::Data& mData; Token getStringToken(); @@ -38,7 +44,7 @@ namespace CSMFilter public: - Parser(); + Parser (const CSMWorld::Data& data); bool parse (const std::string& filter); ///< Discards any previous calls to parse diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index b691a5e169..98d23efdba 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -1,8 +1,8 @@ #include "editwidget.hpp" -CSVFilter::EditWidget::EditWidget (QWidget *parent) -: QLineEdit (parent) +CSVFilter::EditWidget::EditWidget (const CSMWorld::Data& data, QWidget *parent) +: QLineEdit (parent), mParser (data) { mPalette = palette(); connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index 76b484de96..72b2659d59 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -9,6 +9,11 @@ #include "../../model/filter/parser.hpp" #include "../../model/filter/node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSVFilter { class EditWidget : public QLineEdit @@ -20,7 +25,7 @@ namespace CSVFilter public: - EditWidget (QWidget *parent = 0); + EditWidget (const CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/filter/filterbox.cpp b/apps/opencs/view/filter/filterbox.cpp index 495abf8713..af449437bb 100644 --- a/apps/opencs/view/filter/filterbox.cpp +++ b/apps/opencs/view/filter/filterbox.cpp @@ -5,14 +5,14 @@ #include "recordfilterbox.hpp" -CSVFilter::FilterBox::FilterBox (QWidget *parent) +CSVFilter::FilterBox::FilterBox (const CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); layout->setContentsMargins (0, 0, 0, 0); - RecordFilterBox *recordFilterBox = new RecordFilterBox (this); + RecordFilterBox *recordFilterBox = new RecordFilterBox (data, this); layout->addWidget (recordFilterBox); diff --git a/apps/opencs/view/filter/filterbox.hpp b/apps/opencs/view/filter/filterbox.hpp index d3806876df..60d2f038f3 100644 --- a/apps/opencs/view/filter/filterbox.hpp +++ b/apps/opencs/view/filter/filterbox.hpp @@ -5,6 +5,11 @@ #include "../../model/filter/node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSVFilter { class FilterBox : public QWidget @@ -13,7 +18,7 @@ namespace CSVFilter public: - FilterBox (QWidget *parent = 0); + FilterBox (const CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/filter/recordfilterbox.cpp b/apps/opencs/view/filter/recordfilterbox.cpp index 3b5f73f474..6b1831e301 100644 --- a/apps/opencs/view/filter/recordfilterbox.cpp +++ b/apps/opencs/view/filter/recordfilterbox.cpp @@ -6,7 +6,7 @@ #include "editwidget.hpp" -CSVFilter::RecordFilterBox::RecordFilterBox (QWidget *parent) +CSVFilter::RecordFilterBox::RecordFilterBox (const CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); @@ -15,7 +15,7 @@ CSVFilter::RecordFilterBox::RecordFilterBox (QWidget *parent) layout->addWidget (new QLabel ("Record Filter", this)); - EditWidget *editWidget = new EditWidget (this); + EditWidget *editWidget = new EditWidget (data, this); layout->addWidget (editWidget); diff --git a/apps/opencs/view/filter/recordfilterbox.hpp b/apps/opencs/view/filter/recordfilterbox.hpp index 64c1848a85..6b1b0e9bb6 100644 --- a/apps/opencs/view/filter/recordfilterbox.hpp +++ b/apps/opencs/view/filter/recordfilterbox.hpp @@ -9,6 +9,11 @@ #include "../../model/filter/node.hpp" +namespace CSMWorld +{ + class Data; +} + namespace CSVFilter { class RecordFilterBox : public QWidget @@ -17,7 +22,7 @@ namespace CSVFilter public: - RecordFilterBox (QWidget *parent = 0); + RecordFilterBox (const CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index a43ae2dacb..1e05fbf51c 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -25,7 +25,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->insertWidget (0, mTable = new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete()), 2); - CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (this); + CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this); layout->insertWidget (0, filterBox); From 25e6380884f4b9e9495516506c90975a68910e9a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 17:40:00 +0200 Subject: [PATCH 03/40] implemented use of predefined filters --- apps/opencs/model/filter/parser.cpp | 67 +++++++++++++++++++++++------ apps/opencs/model/filter/parser.hpp | 2 +- apps/opencs/model/world/data.cpp | 10 +++++ apps/opencs/model/world/data.hpp | 4 ++ 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 2cf882f2df..b800faa1e1 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -8,6 +8,8 @@ #include #include "../world/columns.hpp" +#include "../world/data.hpp" +#include "../world/idcollection.hpp" #include "booleannode.hpp" #include "ornode.hpp" @@ -31,6 +33,7 @@ namespace CSMFilter Type_OpenSquare, Type_CloseSquare, Type_Comma, + Type_OneShot, Type_Keyword_True, ///< \attention Keyword enums must be arranged continuously. Type_Keyword_False, Type_Keyword_And, @@ -208,6 +211,7 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() case '[': ++mIndex; return Token (Token::Type_OpenSquare); case ']': ++mIndex; return Token (Token::Type_CloseSquare); case ',': ++mIndex; return Token (Token::Type_Comma); + case '?': ++mIndex; return Token (Token::Type_OneShot); } if (c=='"' || c=='_' || std::isalpha (c)) @@ -509,7 +513,7 @@ void CSMFilter::Parser::error() CSMFilter::Parser::Parser (const CSMWorld::Data& data) : mIndex (0), mError (false), mData (data) {} -bool CSMFilter::Parser::parse (const std::string& filter) +bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined) { // reset mFilter.reset(); @@ -517,23 +521,62 @@ bool CSMFilter::Parser::parse (const std::string& filter) mInput = filter; mIndex = 0; - boost::shared_ptr node = parseImp (true); + Token token = getNextToken(); - if (mError) - return false; + if (token==Token (Token::Type_OneShot)) + { + boost::shared_ptr node = parseImp (true); - if (getNextToken()!=Token (Token::Type_EOS)) - return false; + if (mError) + return false; - if (node) - mFilter = node; + if (getNextToken()!=Token (Token::Type_EOS)) + { + error(); + return false; + } + + if (node) + mFilter = node; + else + { + // Empty filter string equals to filter "true". + mFilter.reset (new BooleanNode (true)); + } + + return true; + } + else if (token.mType==Token::Type_String && allowPredefined) + { + if (getNextToken()!=Token (Token::Type_EOS)) + { + error(); + return false; + } + + int index = mData.getFilters().searchId (token.mString); + + if (index==-1) + { + error(); + return false; + } + + const CSMWorld::Record& record = mData.getFilters().getRecord (index); + + if (record.isDeleted()) + { + error(); + return false; + } + + return parse (record.get().mFilter, false); + } else { - // Empty filter string equals to filter "true". - mFilter.reset (new BooleanNode (true)); + error(); + return false; } - - return true; } boost::shared_ptr CSMFilter::Parser::getFilter() const diff --git a/apps/opencs/model/filter/parser.hpp b/apps/opencs/model/filter/parser.hpp index c26168611d..fbaf6972e2 100644 --- a/apps/opencs/model/filter/parser.hpp +++ b/apps/opencs/model/filter/parser.hpp @@ -46,7 +46,7 @@ namespace CSMFilter Parser (const CSMWorld::Data& data); - bool parse (const std::string& filter); + bool parse (const std::string& filter, bool allowPredefined = true); ///< Discards any previous calls to parse /// /// \return Success? diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 4a5dcb38fb..b9f6d17186 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -316,6 +316,16 @@ CSMWorld::RefCollection& CSMWorld::Data::getReferences() return mRefs; } +const CSMWorld::IdCollection& CSMWorld::Data::getFilters() const +{ + return mFilters; +} + +CSMWorld::IdCollection& CSMWorld::Data::getFilters() +{ + return mFilters; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index aebdd6ecda..2f8a2117e0 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -119,6 +119,10 @@ namespace CSMWorld RefCollection& getReferences(); + const IdCollection& getFilters() const; + + IdCollection& getFilters(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// From 7e02c9acf229daad0a17f03c113dfda1c1b479ab Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 18:53:11 +0200 Subject: [PATCH 04/40] added filter text column to filter table --- apps/opencs/model/world/columnimp.hpp | 25 +++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 1 + apps/opencs/model/world/columns.hpp | 1 + apps/opencs/model/world/data.cpp | 1 + 4 files changed, 28 insertions(+) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 6c31fddf39..1a2bf9df13 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1191,6 +1191,31 @@ namespace CSMWorld return true; } }; + + template + struct FilterColumn : public Column + { + FilterColumn() : Column (Columns::ColumnId_Filter, ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mFilter.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mFilter = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index f6eb8fe34e..b206322582 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -144,6 +144,7 @@ namespace CSMWorld { ColumnId_MaxThrust, "Max Thrust" }, { ColumnId_Magical, "Magical" }, { ColumnId_Silver, "Silver" }, + { ColumnId_Filter, "Filter" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 28da60e938..9a39e16780 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -138,6 +138,7 @@ namespace CSMWorld ColumnId_MaxThrust = 106, ColumnId_Magical = 107, ColumnId_Silver = 108, + ColumnId_Filter = 109, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b9f6d17186..fbdbb44136 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -150,6 +150,7 @@ CSMWorld::Data::Data() : mRefs (mCells) mFilters.addColumn (new StringIdColumn); mFilters.addColumn (new RecordStateColumn); + mFilters.addColumn (new FilterColumn); mFilters.addColumn (new DescriptionColumn); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); From d007d4dc9a921bcc592790182b54edb58278a909 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Aug 2013 19:12:47 +0200 Subject: [PATCH 05/40] allow colons in names (filter) --- apps/opencs/model/filter/parser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index b800faa1e1..2320aa0bec 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -92,7 +92,7 @@ CSMFilter::Token CSMFilter::Parser::getStringToken() { char c = mInput[mIndex]; - if (std::isalpha (c) || c=='_' || (!string.empty() && std::isdigit (c)) || c=='"' || + if (std::isalpha (c) || c==':' || c=='_' || (!string.empty() && std::isdigit (c)) || c=='"' || (!string.empty() && string[0]=='"')) string += c; else @@ -214,7 +214,7 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() case '?': ++mIndex; return Token (Token::Type_OneShot); } - if (c=='"' || c=='_' || std::isalpha (c)) + if (c=='"' || c=='_' || std::isalpha (c) || c==':') return getStringToken(); if (c=='-' || c=='.' || std::isdigit (c)) From abd03245d783a3001842d109398e990c9946181d Mon Sep 17 00:00:00 2001 From: Marek Kochanowicz Date: Sat, 24 Aug 2013 19:17:44 +0200 Subject: [PATCH 06/40] Adding .directory to gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 776e2b6591..8aa02070b8 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ data CMakeLists.txt.user *.swp *.swo +.directory From c57fb4fc4fae7e0d9e505bfc08d0b87e2442cfc0 Mon Sep 17 00:00:00 2001 From: sirherrbatka Date: Sat, 24 Aug 2013 19:20:12 +0200 Subject: [PATCH 07/40] Delete .directory --- files/opencs/raster/.directory | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 files/opencs/raster/.directory diff --git a/files/opencs/raster/.directory b/files/opencs/raster/.directory deleted file mode 100644 index a68c37e302..0000000000 --- a/files/opencs/raster/.directory +++ /dev/null @@ -1,8 +0,0 @@ -[Dolphin] -GroupedSorting=true -PreviewsShown=true -SortFoldersFirst=false -Timestamp=2013,8,23,12,44,33 -Version=3 -ViewMode=2 -VisibleRoles=Compact_text,Compact_size From c6d2d1999ac79c7c2ddfcb3527b537f9dd75e71f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 Aug 2013 17:40:08 +0200 Subject: [PATCH 08/40] Fix an item duplication glitch --- apps/openmw/mwgui/container.cpp | 9 +++++++-- apps/openmw/mwgui/containeritemmodel.cpp | 9 ++++----- apps/openmw/mwgui/inventoryitemmodel.cpp | 9 ++++----- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 85c2cf5fb1..bc869e5fef 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -88,8 +88,13 @@ namespace MWGui mDragAndDropWidget->setVisible(false); - targetModel->copyItem(mItem, mDraggedCount); - mSourceModel->removeItem(mItem, mDraggedCount); + // If item is dropped where it was taken from, we don't need to do anything - + // otherwise, do the transfer + if (targetModel != mSourceModel) + { + targetModel->copyItem(mItem, mDraggedCount); + mSourceModel->removeItem(mItem, mDraggedCount); + } mSourceModel->update(); diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index e23b4f77f6..eff8fbcc1b 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -74,13 +74,12 @@ ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item) void ContainerItemModel::copyItem (const ItemStack& item, size_t count) { const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1]; + if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source)) + throw std::runtime_error("Item to copy needs to be from a different container!"); int origCount = item.mBase.getRefData().getCount(); item.mBase.getRefData().setCount(count); - MWWorld::ContainerStoreIterator it = MWWorld::Class::get(source).getContainerStore(source).add(item.mBase, source); - if (*it != item.mBase) - item.mBase.getRefData().setCount(origCount); - else - item.mBase.getRefData().setCount(origCount + count); // item copied onto itself + source.getClass().getContainerStore(source).add(item.mBase, source); + item.mBase.getRefData().setCount(origCount); } void ContainerItemModel::removeItem (const ItemStack& item, size_t count) diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index ec3bb3b301..62a5a75f06 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -40,13 +40,12 @@ ItemModel::ModelIndex InventoryItemModel::getIndex (ItemStack item) void InventoryItemModel::copyItem (const ItemStack& item, size_t count) { + if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor)) + throw std::runtime_error("Item to copy needs to be from a different container!"); int origCount = item.mBase.getRefData().getCount(); item.mBase.getRefData().setCount(count); - MWWorld::ContainerStoreIterator it = MWWorld::Class::get(mActor).getContainerStore(mActor).add(item.mBase, mActor); - if (*it != item.mBase) - item.mBase.getRefData().setCount(origCount); - else - item.mBase.getRefData().setCount(origCount + count); // item copied onto itself + mActor.getClass().getContainerStore(mActor).add(item.mBase, mActor); + item.mBase.getRefData().setCount(origCount); } From e33239eae5677b1e3760422e487dfc60c1b4ea26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20S=C3=B6derberg?= Date: Sun, 25 Aug 2013 23:15:20 +0200 Subject: [PATCH 09/40] Various fixes --- files/mygui/core_layouteditor.xml | 36 ++--- files/mygui/openmw_alchemy_window.layout | 2 +- files/mygui/openmw_button.skin.xml | 2 +- files/mygui/openmw_confirmation_dialog.layout | 12 +- files/mygui/openmw_console.layout | 4 +- files/mygui/openmw_console.skin.xml | 33 +++-- files/mygui/openmw_dialogue_window.layout | 6 +- files/mygui/openmw_dialogue_window_skin.xml | 10 +- files/mygui/openmw_edit.skin.xml | 12 +- files/mygui/openmw_hud_energybar.skin.xml | 16 +-- .../openmw_interactive_messagebox.layout | 12 +- files/mygui/openmw_journal_skin.xml | 6 +- files/mygui/openmw_list.skin.xml | 42 +++--- files/mygui/openmw_messagebox.layout | 14 +- files/mygui/openmw_pointer.xml | 70 +++++----- files/mygui/openmw_progress.skin.xml | 26 ++-- files/mygui/openmw_stats_window.layout | 2 +- files/mygui/openmw_text.skin.xml | 132 +++++++++--------- files/mygui/openmw_tooltips.layout | 2 +- files/mygui/openmw_windows.skin.xml | 86 ++++++------ 20 files changed, 263 insertions(+), 262 deletions(-) diff --git a/files/mygui/core_layouteditor.xml b/files/mygui/core_layouteditor.xml index db917b6efe..007b5e638e 100644 --- a/files/mygui/core_layouteditor.xml +++ b/files/mygui/core_layouteditor.xml @@ -1,25 +1,25 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_alchemy_window.layout b/files/mygui/openmw_alchemy_window.layout index 2241813cfe..4b15ac1bd5 100644 --- a/files/mygui/openmw_alchemy_window.layout +++ b/files/mygui/openmw_alchemy_window.layout @@ -2,7 +2,7 @@ - + diff --git a/files/mygui/openmw_button.skin.xml b/files/mygui/openmw_button.skin.xml index 4f78f7125d..e152a91124 100644 --- a/files/mygui/openmw_button.skin.xml +++ b/files/mygui/openmw_button.skin.xml @@ -62,7 +62,7 @@ - + diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index 024b8ab3b7..47e1fd2b85 100644 --- a/files/mygui/openmw_confirmation_dialog.layout +++ b/files/mygui/openmw_confirmation_dialog.layout @@ -1,19 +1,19 @@ - + - - - + + + - + - + diff --git a/files/mygui/openmw_console.layout b/files/mygui/openmw_console.layout index a65e8b4f4d..bfda40c68b 100644 --- a/files/mygui/openmw_console.layout +++ b/files/mygui/openmw_console.layout @@ -2,7 +2,7 @@ - + @@ -12,7 +12,7 @@ - + diff --git a/files/mygui/openmw_console.skin.xml b/files/mygui/openmw_console.skin.xml index 3537bd662c..219cce39ae 100644 --- a/files/mygui/openmw_console.skin.xml +++ b/files/mygui/openmw_console.skin.xml @@ -1,30 +1,33 @@ + + + - - - + + + - - - - - - - - + + + - - - - + + + + + + + + + diff --git a/files/mygui/openmw_dialogue_window.layout b/files/mygui/openmw_dialogue_window.layout index 9d54f03d07..78daa0705f 100644 --- a/files/mygui/openmw_dialogue_window.layout +++ b/files/mygui/openmw_dialogue_window.layout @@ -15,11 +15,11 @@ - + - - + + diff --git a/files/mygui/openmw_dialogue_window_skin.xml b/files/mygui/openmw_dialogue_window_skin.xml index d4b76daa7f..4f68a90faf 100644 --- a/files/mygui/openmw_dialogue_window_skin.xml +++ b/files/mygui/openmw_dialogue_window_skin.xml @@ -8,11 +8,11 @@ - - - - - + + + + + diff --git a/files/mygui/openmw_edit.skin.xml b/files/mygui/openmw_edit.skin.xml index 76988a5bed..b10854b19e 100644 --- a/files/mygui/openmw_edit.skin.xml +++ b/files/mygui/openmw_edit.skin.xml @@ -21,12 +21,10 @@ + + - - - - - + @@ -39,9 +37,9 @@ - + - + diff --git a/files/mygui/openmw_hud_energybar.skin.xml b/files/mygui/openmw_hud_energybar.skin.xml index f64cb6ca0e..f10908d7b0 100644 --- a/files/mygui/openmw_hud_energybar.skin.xml +++ b/files/mygui/openmw_hud_energybar.skin.xml @@ -43,32 +43,32 @@ - - + + - - + + - - + + - - + + diff --git a/files/mygui/openmw_interactive_messagebox.layout b/files/mygui/openmw_interactive_messagebox.layout index 8d6b6dc34b..d3ac1f8b56 100644 --- a/files/mygui/openmw_interactive_messagebox.layout +++ b/files/mygui/openmw_interactive_messagebox.layout @@ -3,16 +3,16 @@ - - - + + + - - + + - + diff --git a/files/mygui/openmw_journal_skin.xml b/files/mygui/openmw_journal_skin.xml index 9fc5e4c7f0..ca6d309d79 100644 --- a/files/mygui/openmw_journal_skin.xml +++ b/files/mygui/openmw_journal_skin.xml @@ -2,9 +2,9 @@ - - - + + + diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index 54143f270f..02c11c3549 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -5,8 +5,8 @@ - - + + @@ -43,8 +43,8 @@ - - + + @@ -89,17 +89,17 @@ - - + + - + - - + + @@ -114,9 +114,9 @@ - - - + + + @@ -144,9 +144,9 @@ - - - + + + @@ -157,12 +157,12 @@ - - - - + + + + - + @@ -171,7 +171,7 @@ - + diff --git a/files/mygui/openmw_messagebox.layout b/files/mygui/openmw_messagebox.layout index 3d91a289a4..dfdb57648d 100644 --- a/files/mygui/openmw_messagebox.layout +++ b/files/mygui/openmw_messagebox.layout @@ -2,17 +2,17 @@ - - - - + + + + - - + + diff --git a/files/mygui/openmw_pointer.xml b/files/mygui/openmw_pointer.xml index cf21037f8e..a55a5453c0 100644 --- a/files/mygui/openmw_pointer.xml +++ b/files/mygui/openmw_pointer.xml @@ -1,39 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_progress.skin.xml b/files/mygui/openmw_progress.skin.xml index 635e40fb29..aa994fea7a 100644 --- a/files/mygui/openmw_progress.skin.xml +++ b/files/mygui/openmw_progress.skin.xml @@ -17,7 +17,7 @@ - + @@ -25,41 +25,41 @@ - - + + - + - - + + - - + + - - + + - - - + + + diff --git a/files/mygui/openmw_stats_window.layout b/files/mygui/openmw_stats_window.layout index dec962f05d..5ae3f96caf 100644 --- a/files/mygui/openmw_stats_window.layout +++ b/files/mygui/openmw_stats_window.layout @@ -219,7 +219,7 @@ - + diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index 6959c1f5b1..6a1dea60bf 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -4,46 +4,46 @@ - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + @@ -51,36 +51,36 @@ - - - - + + + + - - - - - + + + + + - - - - - + + + + + - + - - - + + + @@ -93,9 +93,9 @@ - - - + + + @@ -108,9 +108,9 @@ - - - + + + @@ -123,9 +123,9 @@ - - - + + + @@ -138,46 +138,46 @@ - + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + diff --git a/files/mygui/openmw_tooltips.layout b/files/mygui/openmw_tooltips.layout index bec6dd87c6..624c133f26 100644 --- a/files/mygui/openmw_tooltips.layout +++ b/files/mygui/openmw_tooltips.layout @@ -200,7 +200,7 @@ - + diff --git a/files/mygui/openmw_windows.skin.xml b/files/mygui/openmw_windows.skin.xml index e8861578f8..22586716cd 100644 --- a/files/mygui/openmw_windows.skin.xml +++ b/files/mygui/openmw_windows.skin.xml @@ -97,26 +97,26 @@ - + - + - + - + - + - + - + - + @@ -167,7 +167,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -207,7 +207,7 @@ - + @@ -218,7 +218,7 @@ - + @@ -230,25 +230,25 @@ - + - + - + - + @@ -256,56 +256,56 @@ - + - + - + - + - + - + - + - + @@ -390,9 +390,9 @@ - - - + + + @@ -415,10 +415,10 @@ ------------------------------------------------------ --> - - - - + + + + @@ -555,10 +555,10 @@ - - - - + + + + @@ -692,10 +692,10 @@ - - - - + + + + @@ -835,9 +835,9 @@ - - - + + + From 45083fc89e6c0e8d6019cf33fe5611980d769d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20S=C3=B6derberg?= Date: Sun, 25 Aug 2013 23:15:29 +0200 Subject: [PATCH 10/40] Chargen updates --- files/mygui/openmw_chargen_birth.layout | 13 ++- files/mygui/openmw_chargen_class.layout | 92 +++++++++---------- .../openmw_chargen_class_description.layout | 16 ++-- .../mygui/openmw_chargen_create_class.layout | 36 ++++---- ...penmw_chargen_generate_class_result.layout | 12 +-- files/mygui/openmw_chargen_race.layout | 14 +-- files/mygui/openmw_chargen_review.layout | 14 +-- .../openmw_chargen_select_attribute.layout | 16 ++-- .../mygui/openmw_chargen_select_skill.layout | 54 +++++------ 9 files changed, 134 insertions(+), 133 deletions(-) diff --git a/files/mygui/openmw_chargen_birth.layout b/files/mygui/openmw_chargen_birth.layout index 75f741271f..e8d959ba22 100644 --- a/files/mygui/openmw_chargen_birth.layout +++ b/files/mygui/openmw_chargen_birth.layout @@ -1,20 +1,19 @@ - + - + - - + + - - + - + diff --git a/files/mygui/openmw_chargen_class.layout b/files/mygui/openmw_chargen_class.layout index 6d159fe619..aac97870c7 100644 --- a/files/mygui/openmw_chargen_class.layout +++ b/files/mygui/openmw_chargen_class.layout @@ -1,66 +1,66 @@ - + - + - - + + - + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - + diff --git a/files/mygui/openmw_chargen_class_description.layout b/files/mygui/openmw_chargen_class_description.layout index 7050f1e3eb..e003f22c19 100644 --- a/files/mygui/openmw_chargen_class_description.layout +++ b/files/mygui/openmw_chargen_class_description.layout @@ -1,22 +1,22 @@ - + + - - - - - - + + + + - + + diff --git a/files/mygui/openmw_chargen_create_class.layout b/files/mygui/openmw_chargen_create_class.layout index 9677f438ff..e9c4146a0b 100644 --- a/files/mygui/openmw_chargen_create_class.layout +++ b/files/mygui/openmw_chargen_create_class.layout @@ -1,14 +1,15 @@ - + + - - + + - + - + @@ -30,30 +31,30 @@ - - + + - - - - - + + + + + - - - - - + + + + + @@ -72,5 +73,6 @@ + diff --git a/files/mygui/openmw_chargen_generate_class_result.layout b/files/mygui/openmw_chargen_generate_class_result.layout index 9ee3e07015..f7178042fe 100644 --- a/files/mygui/openmw_chargen_generate_class_result.layout +++ b/files/mygui/openmw_chargen_generate_class_result.layout @@ -1,26 +1,26 @@ - + - - + + - + - + - + diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index 0f63ba700e..1290795edc 100644 --- a/files/mygui/openmw_chargen_race.layout +++ b/files/mygui/openmw_chargen_race.layout @@ -9,7 +9,7 @@ - + @@ -22,7 +22,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -46,7 +46,7 @@ - + @@ -65,17 +65,17 @@ - + - + - + diff --git a/files/mygui/openmw_chargen_review.layout b/files/mygui/openmw_chargen_review.layout index 84b105bd04..408d4f471e 100644 --- a/files/mygui/openmw_chargen_review.layout +++ b/files/mygui/openmw_chargen_review.layout @@ -1,10 +1,10 @@ - + - + @@ -24,7 +24,7 @@ - + @@ -46,7 +46,7 @@ - + @@ -106,12 +106,12 @@ - - + + - + diff --git a/files/mygui/openmw_chargen_select_attribute.layout b/files/mygui/openmw_chargen_select_attribute.layout index b847bcd3bf..f0f72bb0fa 100644 --- a/files/mygui/openmw_chargen_select_attribute.layout +++ b/files/mygui/openmw_chargen_select_attribute.layout @@ -10,14 +10,14 @@ - - - - - - - - + + + + + + + + diff --git a/files/mygui/openmw_chargen_select_skill.layout b/files/mygui/openmw_chargen_select_skill.layout index 90ae477e5b..dc1798995b 100644 --- a/files/mygui/openmw_chargen_select_skill.layout +++ b/files/mygui/openmw_chargen_select_skill.layout @@ -14,45 +14,45 @@ - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + From 5af89a9e8f704b31a9fe1d1ff36f987c18fd0c67 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 Aug 2013 00:13:42 +0200 Subject: [PATCH 11/40] Fix an AABB assert for loading empty exterior cells --- apps/openmw/mwrender/renderingmanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ade871a94b..a7e35fa195 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -652,7 +652,8 @@ void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell) Ogre::Vector2 center(cell->mCell->getGridX() + 0.5, cell->mCell->getGridY() + 0.5); dims.merge(mTerrain->getWorldBoundingBox(center)); - mTerrain->update(dims.getCenter()); + if (dims.isFinite()) + mTerrain->update(dims.getCenter()); mLocalMap->requestMap(cell, dims.getMinimum().z, dims.getMaximum().z); } From 3f8a69b4ad8ea949b753c3598912b917e791b62c Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 Aug 2013 00:14:02 +0200 Subject: [PATCH 12/40] Don't crash when trying to delete a reference that doesn't exist anymore --- apps/openmw/mwworld/cellstore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 8bb3d3c8d1..0c145ab600 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -43,7 +43,8 @@ namespace MWWorld // Skip this when reference was deleted. // TODO: Support respawning references, in this case, we need to track it somehow. if (ref.mDeleted) { - mList.erase(iter); + if (iter != mList.end()) + mList.erase(iter); return; } From bd6dd071aa5c84aab6611a8e9a644c5d2a2050d9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 24 Aug 2013 17:42:40 -0700 Subject: [PATCH 13/40] Use the non-accumulation root's parent as the accumulation root This relies on the non-accumulation root not being the skeleton root. I haven't found an instance where this isn't the case. --- apps/openmw/mwrender/animation.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index f44f53a741..545060fe3a 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -64,7 +64,7 @@ void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectL Animation::Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node) : mPtr(ptr) , mCamera(NULL) - , mInsert(NULL) + , mInsert(node) , mSkelBase(NULL) , mAccumRoot(NULL) , mNonAccumRoot(NULL) @@ -74,20 +74,14 @@ Animation::Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node) { for(size_t i = 0;i < sNumGroups;i++) mAnimationValuePtr[i].bind(OGRE_NEW AnimationValue(this)); - mInsert = node->createChildSceneNode(); } Animation::~Animation() { - if(mInsert) - { - mAnimSources.clear(); + mAnimSources.clear(); - Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - destroyObjectList(sceneMgr, mObjectRoot); - - sceneMgr->destroySceneNode(mInsert); - } + Ogre::SceneManager *sceneMgr = mInsert->getCreator(); + destroyObjectList(sceneMgr, mObjectRoot); } @@ -268,8 +262,13 @@ void Animation::addAnimSource(const std::string &model) if(!mAccumRoot && grp == 0) { - mAccumRoot = mInsert; mNonAccumRoot = dstval->getNode(); + mAccumRoot = mNonAccumRoot->getParent(); + if(!mAccumRoot) + { + std::cerr<< "Non-Accum root for "<getParentSceneNode()->getScale(); + Ogre::Vector3 extents = getWorldBounds().getSize(); float size = std::max(std::max(extents.x, extents.y), extents.z); bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && From 0463dc06536795bc0d793d26c11481c27a565718 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 25 Aug 2013 11:03:23 -0700 Subject: [PATCH 14/40] Use a smaller static geometry size for interior cells --- apps/openmw/mwrender/objects.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 337327dc49..fd81baf6ed 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -130,7 +130,10 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh) // - the culling will be more inefficient // If it is set too low: // - there will be too many batches. - sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); + if(ptr.getCell()->isExterior()) + sg->setRegionDimensions(Ogre::Vector3(2048,2048,2048)); + else + sg->setRegionDimensions(Ogre::Vector3(1024,1024,1024)); sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); From 3843357cd2d9f8370bb7b2a309979c8a0db58d64 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 25 Aug 2013 11:04:55 -0700 Subject: [PATCH 15/40] Fix actor stepping --- apps/openmw/mwworld/physicssystem.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 97aa7dffe5..36ea8ccc64 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -29,7 +29,7 @@ namespace MWWorld { static const float sMaxSlope = 60.0f; - static const float sStepSize = 30.0f; + static const float sStepSize = 32.0f; // Arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared. static const int sMaxIterations = 8; @@ -48,16 +48,15 @@ namespace MWWorld OEngine::Physic::ActorTracer tracer, stepper; stepper.doTrace(colobj, position, position+Ogre::Vector3(0.0f,0.0f,sStepSize), engine); - if(stepper.mFraction == 0.0f) + if(stepper.mFraction < std::numeric_limits::epsilon()) return false; tracer.doTrace(colobj, stepper.mEndPos, stepper.mEndPos + velocity*remainingTime, engine); - if(tracer.mFraction < std::numeric_limits::epsilon() || - (tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) > sMaxSlope)) + if(tracer.mFraction < std::numeric_limits::epsilon()) return false; stepper.doTrace(colobj, tracer.mEndPos, tracer.mEndPos-Ogre::Vector3(0.0f,0.0f,sStepSize), engine); - if(getSlope(stepper.mPlaneNormal) <= sMaxSlope) + if(stepper.mFraction < 1.0f && getSlope(stepper.mPlaneNormal) <= sMaxSlope) { // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall. position = stepper.mEndPos; From f2889e4bb53a8fe0c94043faede5d5e43d6ea2e9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 25 Aug 2013 15:10:22 -0700 Subject: [PATCH 16/40] Remove unused functions and parameters --- apps/openmw/mwworld/physicssystem.cpp | 23 ++--------------------- apps/openmw/mwworld/physicssystem.hpp | 6 +----- apps/openmw/mwworld/worldimp.cpp | 2 +- 3 files changed, 4 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 36ea8ccc64..433fe08925 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -256,7 +256,7 @@ namespace MWWorld return mEngine; } - std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world, float queryDistance) + std::pair PhysicsSystem::getFacedHandle(float queryDistance) { Ray ray = mRender.getCamera()->getCameraToViewportRay(0.5, 0.5); @@ -266,8 +266,7 @@ namespace MWWorld btVector3 dir(dir_.x, dir_.y, dir_.z); btVector3 dest = origin + dir * queryDistance; - std::pair result; - /*auto*/ result = mEngine->rayTest(origin, dest); + std::pair result = mEngine->rayTest(origin, dest); result.second *= queryDistance; return std::make_pair (result.second, result.first); @@ -338,24 +337,6 @@ namespace MWWorld } - btVector3 PhysicsSystem::getRayPoint(float extent) - { - //get a ray pointing to the center of the viewport - Ray centerRay = mRender.getCamera()->getCameraToViewportRay( - mRender.getViewport()->getWidth()/2, - mRender.getViewport()->getHeight()/2); - btVector3 result(centerRay.getPoint(extent).x,centerRay.getPoint(extent).y,centerRay.getPoint(extent).z); - return result; - } - - btVector3 PhysicsSystem::getRayPoint(float extent, float mouseX, float mouseY) - { - //get a ray pointing to the center of the viewport - Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); - btVector3 result(centerRay.getPoint(extent).x,centerRay.getPoint(extent).y,centerRay.getPoint(extent).z); - return result; - } - bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to, bool raycastingObjectOnly,bool ignoreHeightMap) { btVector3 _from, _to; diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index f76b4d29c7..3dcd088f54 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -56,7 +56,7 @@ namespace MWWorld std::vector getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr); - std::pair getFacedHandle (MWWorld::World& world, float queryDistance); + std::pair getFacedHandle(float queryDistance); std::pair getHitContact(const std::string &name, const Ogre::Vector3 &origin, const Ogre::Quaternion &orientation, @@ -64,10 +64,6 @@ namespace MWWorld std::vector < std::pair > getFacedHandles (float queryDistance); std::vector < std::pair > getFacedHandles (float mouseX, float mouseY, float queryDistance); - btVector3 getRayPoint(float extent); - btVector3 getRayPoint(float extent, float mouseX, float mouseY); - - // cast ray, return true if it hit something. if raycasringObjectOnlt is set to false, it ignores NPCs and objects with no collisions. bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to, bool raycastingObjectOnly = true,bool ignoreHeightMap = false); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index eee9c7a199..09dc0493e8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -761,7 +761,7 @@ namespace MWWorld std::pair result; if (!mRendering->occlusionQuerySupported()) - result = mPhysics->getFacedHandle (*this, getMaxActivationDistance ()); + result = mPhysics->getFacedHandle (getMaxActivationDistance ()); else result = std::make_pair (mFacedDistance, mFacedHandle); From 937f5b11a2795d91a033da953405f6f7b5c7a665 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 12:25:19 +0200 Subject: [PATCH 17/40] fixed broken record deletion --- apps/opencs/model/world/collection.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index 526c07815e..6cf31d0a4f 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -236,14 +236,15 @@ namespace CSMWorld if (iter->second>=index+count) { iter->second -= count; + ++iter; } else { mIndex.erase (iter++); } } - - ++iter; + else + ++iter; } } From 20bd0707dcff43888b0d55006a850ebb8c216763 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 12:25:52 +0200 Subject: [PATCH 18/40] avoid use of column number literals --- apps/opencs/model/world/commands.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 43ecaca63c..f6f421c6ae 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -69,7 +69,9 @@ CSMWorld::RevertCommand::~RevertCommand() void CSMWorld::RevertCommand::redo() { - QModelIndex index = mModel.getModelIndex (mId, 1); + int column = mModel.findColumnIndex (Columns::ColumnId_Modification); + + QModelIndex index = mModel.getModelIndex (mId, column); RecordBase::State state = static_cast (mModel.data (index).toInt()); if (state==RecordBase::State_ModifiedOnly) @@ -102,7 +104,9 @@ CSMWorld::DeleteCommand::~DeleteCommand() void CSMWorld::DeleteCommand::redo() { - QModelIndex index = mModel.getModelIndex (mId, 1); + int column = mModel.findColumnIndex (Columns::ColumnId_Modification); + + QModelIndex index = mModel.getModelIndex (mId, column); RecordBase::State state = static_cast (mModel.data (index).toInt()); if (state==RecordBase::State_ModifiedOnly) From aa935ff03d86709a629295e232be743ce8c15e3a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 12:49:13 +0200 Subject: [PATCH 19/40] update tables on filter record changes --- apps/opencs/view/filter/editwidget.cpp | 36 +++++++++++++++++++-- apps/opencs/view/filter/editwidget.hpp | 10 +++++- apps/opencs/view/filter/filterbox.cpp | 2 +- apps/opencs/view/filter/filterbox.hpp | 2 +- apps/opencs/view/filter/recordfilterbox.cpp | 2 +- apps/opencs/view/filter/recordfilterbox.hpp | 2 +- 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 98d23efdba..708d450325 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -1,11 +1,27 @@ #include "editwidget.hpp" -CSVFilter::EditWidget::EditWidget (const CSMWorld::Data& data, QWidget *parent) +#include + +#include "../../model/world/data.hpp" + +CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) : QLineEdit (parent), mParser (data) { mPalette = palette(); connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); + + QAbstractItemModel *model = data.getTableModel (CSMWorld::UniversalId::Type_Filters); + + connect (model, SIGNAL (dataChanged (const QModelIndex &, const QModelIndex&)), + this, SLOT (filterDataChanged (const QModelIndex &, const QModelIndex&)), + Qt::QueuedConnection); + connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)), + this, SLOT (filterRowsRemoved (const QModelIndex&, int, int)), + Qt::QueuedConnection); + connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)), + this, SLOT (filterRowsInserted (const QModelIndex&, int, int)), + Qt::QueuedConnection); } void CSVFilter::EditWidget::textChanged (const QString& text) @@ -23,4 +39,20 @@ void CSVFilter::EditWidget::textChanged (const QString& text) /// \todo improve error reporting; mark only the faulty part } -} \ No newline at end of file +} + +void CSVFilter::EditWidget::filterDataChanged (const QModelIndex& topLeft, + const QModelIndex& bottomRight) +{ + textChanged (text()); +} + +void CSVFilter::EditWidget::filterRowsRemoved (const QModelIndex& parent, int start, int end) +{ + textChanged (text()); +} + +void CSVFilter::EditWidget::filterRowsInserted (const QModelIndex& parent, int start, int end) +{ + textChanged (text()); +} diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index 72b2659d59..31904e624f 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -9,6 +9,8 @@ #include "../../model/filter/parser.hpp" #include "../../model/filter/node.hpp" +class QModelIndex; + namespace CSMWorld { class Data; @@ -25,7 +27,7 @@ namespace CSVFilter public: - EditWidget (const CSMWorld::Data& data, QWidget *parent = 0); + EditWidget (CSMWorld::Data& data, QWidget *parent = 0); signals: @@ -34,6 +36,12 @@ namespace CSVFilter private slots: void textChanged (const QString& text); + + void filterDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); + + void filterRowsRemoved (const QModelIndex& parent, int start, int end); + + void filterRowsInserted (const QModelIndex& parent, int start, int end); }; } diff --git a/apps/opencs/view/filter/filterbox.cpp b/apps/opencs/view/filter/filterbox.cpp index af449437bb..2731708841 100644 --- a/apps/opencs/view/filter/filterbox.cpp +++ b/apps/opencs/view/filter/filterbox.cpp @@ -5,7 +5,7 @@ #include "recordfilterbox.hpp" -CSVFilter::FilterBox::FilterBox (const CSMWorld::Data& data, QWidget *parent) +CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); diff --git a/apps/opencs/view/filter/filterbox.hpp b/apps/opencs/view/filter/filterbox.hpp index 60d2f038f3..2524fa0a38 100644 --- a/apps/opencs/view/filter/filterbox.hpp +++ b/apps/opencs/view/filter/filterbox.hpp @@ -18,7 +18,7 @@ namespace CSVFilter public: - FilterBox (const CSMWorld::Data& data, QWidget *parent = 0); + FilterBox (CSMWorld::Data& data, QWidget *parent = 0); signals: diff --git a/apps/opencs/view/filter/recordfilterbox.cpp b/apps/opencs/view/filter/recordfilterbox.cpp index 6b1831e301..c405177b01 100644 --- a/apps/opencs/view/filter/recordfilterbox.cpp +++ b/apps/opencs/view/filter/recordfilterbox.cpp @@ -6,7 +6,7 @@ #include "editwidget.hpp" -CSVFilter::RecordFilterBox::RecordFilterBox (const CSMWorld::Data& data, QWidget *parent) +CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *parent) : QWidget (parent) { QHBoxLayout *layout = new QHBoxLayout (this); diff --git a/apps/opencs/view/filter/recordfilterbox.hpp b/apps/opencs/view/filter/recordfilterbox.hpp index 6b1b0e9bb6..057d69518d 100644 --- a/apps/opencs/view/filter/recordfilterbox.hpp +++ b/apps/opencs/view/filter/recordfilterbox.hpp @@ -22,7 +22,7 @@ namespace CSVFilter public: - RecordFilterBox (const CSMWorld::Data& data, QWidget *parent = 0); + RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0); signals: From 2e9948e86a43498dc0f09babb8ed143870cf17c5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Aug 2013 14:40:34 +0200 Subject: [PATCH 20/40] improved one-shot filter handling; allow empty pre-defined filters --- apps/opencs/model/filter/parser.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 2320aa0bec..abdc3bab39 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -47,7 +47,7 @@ namespace CSMFilter std::string mString; double mNumber; - Token (Type type); + Token (Type type = Type_None); Token (const std::string& string); @@ -521,9 +521,12 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined) mInput = filter; mIndex = 0; - Token token = getNextToken(); + Token token; - if (token==Token (Token::Type_OneShot)) + if (allowPredefined) + token = getNextToken(); + + if (!allowPredefined || token==Token (Token::Type_OneShot)) { boost::shared_ptr node = parseImp (true); From d3d6dfbde8e0296bf35ebd9c1e501062193bed99 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 Aug 2013 15:48:13 +0200 Subject: [PATCH 21/40] Refactored loading screen - Add loading progress for data files, global map, terrain - Refactored and improved cell loading progress --- apps/openmw/engine.cpp | 38 +-- apps/openmw/mwbase/windowmanager.hpp | 7 +- apps/openmw/mwgui/loadingscreen.cpp | 261 +++++++++--------- apps/openmw/mwgui/loadingscreen.hpp | 37 ++- apps/openmw/mwgui/mapwindow.cpp | 15 +- apps/openmw/mwgui/mapwindow.hpp | 7 + apps/openmw/mwgui/windowmanagerimp.cpp | 72 +++-- apps/openmw/mwgui/windowmanagerimp.hpp | 10 +- apps/openmw/mwinput/inputmanagerimp.cpp | 171 ++++++------ apps/openmw/mwinput/inputmanagerimp.hpp | 7 +- apps/openmw/mwrender/globalmap.cpp | 12 +- apps/openmw/mwrender/globalmap.hpp | 7 +- apps/openmw/mwrender/renderingmanager.cpp | 7 +- apps/openmw/mwworld/esmstore.cpp | 7 +- apps/openmw/mwworld/esmstore.hpp | 7 +- apps/openmw/mwworld/scene.cpp | 123 +++++---- apps/openmw/mwworld/scene.hpp | 6 +- apps/openmw/mwworld/worldimp.cpp | 9 +- components/CMakeLists.txt | 4 + components/esm/esmreader.hpp | 5 + .../loadinglistener/loadinglistener.hpp | 35 +++ components/terrain/quadtreenode.cpp | 7 +- components/terrain/quadtreenode.hpp | 4 +- components/terrain/terrain.cpp | 12 +- components/terrain/terrain.hpp | 13 +- extern/sdl4ogre/sdlinputwrapper.cpp | 13 +- extern/sdl4ogre/sdlinputwrapper.hpp | 2 +- files/mygui/openmw_loading_screen.layout | 3 +- files/mygui/openmw_progress.skin.xml | 15 +- libs/openengine/ogre/renderer.cpp | 20 +- libs/openengine/ogre/renderer.hpp | 2 +- 31 files changed, 551 insertions(+), 387 deletions(-) create mode 100644 components/loadinglistener/loadinglistener.hpp diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 62a15fbf9e..a2eccbaf9a 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -123,6 +123,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch); MWBase::Environment::get().getWindowManager()->onFrame(frametime); + MWBase::Environment::get().getWindowManager()->update(); } catch (const std::exception& e) { @@ -385,26 +386,39 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) loadBSA(); + + // Create input and UI first to set up a bootstrapping environment for + // showing a loading screen and keeping the window responsive while doing so + + std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string(); + bool keybinderUserExists = boost::filesystem::exists(keybinderUser); + MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists); + mEnvironment.setInputManager (input); + + MWGui::WindowManager* window = new MWGui::WindowManager( + mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), + mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding); + mEnvironment.setWindowManager (window); + if (mNewGame) + mEnvironment.getWindowManager()->setNewGame(true); + // Create the world mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins, mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap, mActivationDistanceOverride)); MWBase::Environment::get().getWorld()->setupPlayer(); + input->setPlayer(&mEnvironment.getWorld()->getPlayer()); + + window->initUI(); + window->renderWorldMap(); //Load translation data mTranslationDataStorage.setEncoder(mEncoder); for (size_t i = 0; i < mMaster.size(); i++) mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster[i]); - // Create window manager - this manages all the MW-specific GUI windows Compiler::registerExtensions (mExtensions); - mEnvironment.setWindowManager (new MWGui::WindowManager( - mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), - mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding)); - if (mNewGame) - mEnvironment.getWindowManager()->setNewGame(true); - // Create sound system mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); @@ -422,16 +436,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mEnvironment.setJournal (new MWDialogue::Journal); mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage)); - // Sets up the input system - - // Get the path for the keybinder xml file - std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string(); - bool keybinderUserExists = boost::filesystem::exists(keybinderUser); - - mEnvironment.setInputManager (new MWInput::InputManager (*mOgre, - MWBase::Environment::get().getWorld()->getPlayer(), - *MWBase::Environment::get().getWindowManager(), *this, keybinderUser, keybinderUserExists)); - mEnvironment.getWorld()->renderPlayer(); if (!mNewGame) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 77941a43a0..1cd8672230 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -9,6 +9,8 @@ #include +#include + #include "../mwmechanics/stat.hpp" #include "../mwgui/mode.hpp" @@ -253,9 +255,6 @@ namespace MWBase virtual void executeInConsole (const std::string& path) = 0; - virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0; - virtual void loadingDone() = 0; - virtual void enableRest() = 0; virtual bool getRestEnabled() = 0; virtual bool getJournalAllowed() = 0; @@ -282,6 +281,8 @@ namespace MWBase virtual const Translation::Storage& getTranslationDataStorage() const = 0; virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0; + + virtual Loading::Listener* getLoadingScreen() = 0; }; } diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 547d2fe29d..9b63dfa76d 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -19,20 +19,16 @@ namespace MWGui : mSceneMgr(sceneMgr) , mWindow(rw) , WindowBase("openmw_loading_screen.layout") - , mLoadingOn(false) , mLastRenderTime(0.f) , mLastWallpaperChangeTime(0.f) , mFirstLoad(true) - , mTotalRefsLoading(0) - , mCurrentCellLoading(0) - , mTotalCellsLoading(0) - , mCurrentRefLoading(0) - , mCurrentRefList(0) + , mProgress(0) { getWidget(mLoadingText, "LoadingText"); getWidget(mProgressBar, "ProgressBar"); getWidget(mBackgroundImage, "BackgroundImage"); + mProgressBar->setScrollViewPage(1); mBackgroundMaterial = Ogre::MaterialManager::getSingleton().create("BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mBackgroundMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false); @@ -54,6 +50,11 @@ namespace MWGui mRectangle->setVisible(false); } + void LoadingScreen::setLabel(const std::string &label) + { + mLoadingText->setCaptionWithReplacing(label); + } + LoadingScreen::~LoadingScreen() { delete mRectangle; @@ -64,149 +65,25 @@ namespace MWGui setCoord(0,0,w,h); } - void LoadingScreen::setLoadingProgress (const std::string& stage, int depth, int current, int total) - { - if (!mLoadingOn) - loadingOn(); - - const int numRefLists = 20; - - if (depth == 0) - { - mCurrentCellLoading = current; - mTotalCellsLoading = total; - - mCurrentRefLoading = 0; - mCurrentRefList = 0; - } - else if (depth == 1) - { - mCurrentRefLoading = current; - mTotalRefsLoading = total; - } - - assert (mTotalCellsLoading != 0); - - float refProgress; - if (mTotalRefsLoading <= 1) - refProgress = 1; - else - refProgress = float(mCurrentRefLoading) / float(mTotalRefsLoading-1); - refProgress += mCurrentRefList; - refProgress /= numRefLists; - - assert(refProgress <= 1 && refProgress >= 0); - - if (depth == 1 && mCurrentRefLoading == mTotalRefsLoading-1) - ++mCurrentRefList; - - float progress = (float(mCurrentCellLoading)+refProgress) / float(mTotalCellsLoading); - assert(progress <= 1 && progress >= 0); - - mLoadingText->setCaption(stage); - mProgressBar->setProgressPosition (static_cast(progress * 1000)); - - static float loadingScreenFps = 30.f; - - if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f) - { - float dt = mTimer.getMilliseconds () - mLastRenderTime; - mLastRenderTime = mTimer.getMilliseconds (); - - if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 3000*1) - { - mLastWallpaperChangeTime = mTimer.getMilliseconds (); - changeWallpaper(); - } - - // Turn off rendering except the GUI - mSceneMgr->clearSpecialCaseRenderQueues(); - // SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work. - for (int i = 0; i < Ogre::RENDER_QUEUE_MAX; ++i) - { - if (i > 0 && i < 96) - mSceneMgr->addSpecialCaseRenderQueue(i); - } - mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); - - // always update input before rendering something, otherwise mygui goes crazy when something was entered in the frame before - // (e.g. when using "coc" console command, it would enter an infinite loop and crash due to overflow) - MWBase::Environment::get().getInputManager()->update(0, true); - - Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0)); - - bool hasCompositor = chain->getCompositor ("gbufferFinalizer"); - - - if (!hasCompositor) - { - mWindow->getViewport(0)->setClearEveryFrame(false); - } - else - { - if (!mFirstLoad) - { - mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName()); - mRectangle->setVisible(true); - } - - for (unsigned int i = 0; igetNumCompositors(); ++i) - { - Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), false); - } - } - - MWBase::Environment::get().getWorld ()->getFader ()->update (dt); - - mWindow->update(); - - if (!hasCompositor) - mWindow->getViewport(0)->setClearEveryFrame(true); - else - { - for (unsigned int i = 0; igetNumCompositors(); ++i) - { - Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), true); - } - } - - mRectangle->setVisible(false); - - // resume 3d rendering - mSceneMgr->clearSpecialCaseRenderQueues(); - mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); - } - } - - void LoadingScreen::loadingDone() - { - loadingOff(); - } - void LoadingScreen::loadingOn() { setVisible(true); - mLoadingOn = true; if (mFirstLoad) { changeWallpaper(); - - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_LoadingWallpaper); } else { mBackgroundImage->setImageTexture(""); - MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Loading); } - } + MWBase::Environment::get().getWindowManager()->pushGuiMode(mFirstLoad ? GM_LoadingWallpaper : GM_Loading); + } void LoadingScreen::loadingOff() { setVisible(false); - mLoadingOn = false; - mFirstLoad = false; MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_LoadingWallpaper); @@ -235,4 +112,124 @@ namespace MWGui else std::cerr << "No loading screens found!" << std::endl; } + + void LoadingScreen::setProgressRange (size_t range) + { + mProgressBar->setScrollRange(range+1); + mProgressBar->setScrollPosition(0); + mProgressBar->setTrackSize(0); + mProgress = 0; + } + + void LoadingScreen::setProgress (size_t value) + { + assert(value < mProgressBar->getScrollRange()); + if (value - mProgress < mProgressBar->getScrollRange()/100.f) + return; + mProgress = value; + mProgressBar->setScrollPosition(0); + mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize()); + draw(); + } + + void LoadingScreen::increaseProgress (size_t increase) + { + mProgressBar->setScrollPosition(0); + size_t value = mProgress + increase; + mProgress = value; + assert(mProgress < mProgressBar->getScrollRange()); + mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize()); + draw(); + } + + void LoadingScreen::indicateProgress() + { + float time = (mTimer.getMilliseconds() % 2001) / 1000.f; + if (time > 1) + time = (time-2)*-1; + + mProgressBar->setTrackSize(50); + mProgressBar->setScrollPosition(time * (mProgressBar->getScrollRange()-1)); + draw(); + } + + void LoadingScreen::removeWallpaper() + { + mFirstLoad = false; + } + + void LoadingScreen::draw() + { + const float loadingScreenFps = 20.f; + + if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f) + { + mLastRenderTime = mTimer.getMilliseconds (); + + if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1) + { + mLastWallpaperChangeTime = mTimer.getMilliseconds (); + changeWallpaper(); + } + + // Turn off rendering except the GUI + mSceneMgr->clearSpecialCaseRenderQueues(); + // SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work. + for (int i = 0; i < Ogre::RENDER_QUEUE_MAX; ++i) + { + if (i > 0 && i < 96) + mSceneMgr->addSpecialCaseRenderQueue(i); + } + mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); + + MWBase::Environment::get().getInputManager()->update(0, true); + + Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0)); + + bool hasCompositor = chain->getCompositor ("gbufferFinalizer"); + + + if (!hasCompositor) + { + mWindow->getViewport(0)->setClearEveryFrame(false); + } + else + { + if (!mFirstLoad) + { + mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName()); + mRectangle->setVisible(true); + } + + for (unsigned int i = 0; igetNumCompositors(); ++i) + { + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), false); + } + } + + // First, swap buffers from last draw, then, queue an update of the + // window contents, but don't swap buffers (which would have + // caused a sync / flush and would be expensive). + // We're doing this so we can do some actual loading while the GPU is busy with the render. + // This means the render is lagging a frame behind, but this is hardly noticable. + mWindow->swapBuffers(false); // never Vsync, makes no sense here + mWindow->update(false); + + if (!hasCompositor) + mWindow->getViewport(0)->setClearEveryFrame(true); + else + { + for (unsigned int i = 0; igetNumCompositors(); ++i) + { + Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), true); + } + } + + mRectangle->setVisible(false); + + // resume 3d rendering + mSceneMgr->clearSpecialCaseRenderQueues(); + mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); + } + } } diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index 87cedaa98c..dde8ff63aa 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -5,11 +5,27 @@ #include "windowbase.hpp" +#include + namespace MWGui { - class LoadingScreen : public WindowBase + class LoadingScreen : public WindowBase, public Loading::Listener { public: + virtual void setLabel (const std::string& label); + + /// Indicate that some progress has been made, without specifying how much + virtual void indicateProgress (); + + virtual void loadingOn(); + virtual void loadingOff(); + + virtual void setProgressRange (size_t range); + virtual void setProgress (size_t value); + virtual void increaseProgress (size_t increase); + + virtual void removeWallpaper(); + LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw); virtual ~LoadingScreen(); @@ -30,27 +46,20 @@ namespace MWGui unsigned long mLastRenderTime; Ogre::Timer mTimer; - MyGUI::TextBox* mLoadingText; - MyGUI::ProgressBar* mProgressBar; - MyGUI::ImageBox* mBackgroundImage; + size_t mProgress; - int mCurrentCellLoading; - int mTotalCellsLoading; - int mCurrentRefLoading; - int mTotalRefsLoading; - int mCurrentRefList; + MyGUI::TextBox* mLoadingText; + MyGUI::ScrollBar* mProgressBar; + MyGUI::ImageBox* mBackgroundImage; Ogre::Rectangle2D* mRectangle; Ogre::MaterialPtr mBackgroundMaterial; Ogre::StringVector mResources; - bool mLoadingOn; - - void loadingOn(); - void loadingOff(); - void changeWallpaper(); + + void draw(); }; } diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 0ccfb7e88c..5ed002d7b3 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -260,12 +260,10 @@ namespace MWGui MapWindow::MapWindow(const std::string& cacheDir) : MWGui::WindowPinnableBase("openmw_map_window.layout") , mGlobal(false) + , mGlobalMap(0) { setCoord(500,0,320,300); - mGlobalMapRender = new MWRender::GlobalMap(cacheDir); - mGlobalMapRender->render(); - getWidget(mLocalMap, "LocalMap"); getWidget(mGlobalMap, "GlobalMap"); getWidget(mGlobalMapImage, "GlobalMapImage"); @@ -273,9 +271,6 @@ namespace MWGui getWidget(mPlayerArrowLocal, "CompassLocal"); getWidget(mPlayerArrowGlobal, "CompassGlobal"); - mGlobalMapImage->setImageTexture("GlobalMap.png"); - mGlobalMapOverlay->setImageTexture("GlobalMapOverlay"); - mGlobalMap->setVisible (false); getWidget(mButton, "WorldButton"); @@ -292,6 +287,14 @@ namespace MWGui LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this); } + void MapWindow::renderGlobalMap(Loading::Listener* loadingListener) + { + mGlobalMapRender = new MWRender::GlobalMap(""); + mGlobalMapRender->render(loadingListener); + mGlobalMapImage->setImageTexture("GlobalMap.png"); + mGlobalMapOverlay->setImageTexture("GlobalMapOverlay"); + } + MapWindow::~MapWindow() { delete mGlobalMapRender; diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 3aefc398cf..5518ab4a8f 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -8,6 +8,11 @@ namespace MWRender class GlobalMap; } +namespace Loading +{ + class Listener; +} + namespace MWGui { class LocalMapBase @@ -71,6 +76,8 @@ namespace MWGui void setCellName(const std::string& cellName); + void renderGlobalMap(Loading::Listener* loadingListener); + void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map void cellExplored(int x, int y); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1cb1d80b0a..ad1d9a60b5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -62,6 +62,7 @@ namespace MWGui const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding) : mGuiManager(NULL) + , mConsoleOnlyScripts(consoleOnlyScripts) , mRendering(ogre) , mHud(NULL) , mMap(NULL) @@ -156,7 +157,28 @@ namespace MWGui MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); // Get size info from the Gui object - assert(mGui); + int w = MyGUI::RenderManager::getInstance().getViewSize().width; + int h = MyGUI::RenderManager::getInstance().getViewSize().height; + + mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ()); + mLoadingScreen->onResChange (w,h); + + //set up the hardware cursor manager + mSoftwareCursor = new Cursor(); + mCursorManager = new SFO::SDLCursorManager(); + + MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange); + + MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); + + setUseHardwareCursors(mUseHardwareCursors); + onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); + mCursorManager->cursorVisibilityChange(false); + } + + void WindowManager::initUI() + { + // Get size info from the Gui object int w = MyGUI::RenderManager::getInstance().getViewSize().width; int h = MyGUI::RenderManager::getInstance().getViewSize().height; @@ -169,9 +191,9 @@ namespace MWGui mDragAndDrop->mDragAndDropWidget = dragAndDropWidget; mMenu = new MainMenu(w,h); - mMap = new MapWindow(cacheDir); + mMap = new MapWindow(""); mStatsWindow = new StatsWindow(); - mConsole = new Console(w,h, consoleOnlyScripts); + mConsole = new Console(w,h, mConsoleOnlyScripts); mJournal = JournalWindow::create(JournalViewModel::create ()); mMessageBoxManager = new MessageBoxManager(); mInventoryWindow = new InventoryWindow(mDragAndDrop); @@ -200,13 +222,8 @@ namespace MWGui mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); - mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ()); - mLoadingScreen->onResChange (w,h); - mInputBlocker = mGui->createWidget("",0,0,w,h,MyGUI::Align::Default,"Windows",""); - mSoftwareCursor = new Cursor(); - mHud->setVisible(mHudEnabled); mCharGen = new CharacterCreation(); @@ -225,19 +242,15 @@ namespace MWGui unsetSelectedSpell(); unsetSelectedWeapon(); - //set up the hardware cursor manager - mCursorManager = new SFO::SDLCursorManager(); - - MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange); - - MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); - - setUseHardwareCursors(mUseHardwareCursors); - onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); - mCursorManager->cursorVisibilityChange(false); - // Set up visibility updateVisible(); + + MWBase::Environment::get().getInputManager()->changeInputMode(false); + } + + void WindowManager::renderWorldMap() + { + mMap->renderGlobalMap(mLoadingScreen); } void WindowManager::setNewGame(bool newgame) @@ -329,6 +342,8 @@ namespace MWGui void WindowManager::updateVisible() { + if (!mMap) + return; // UI not created yet // Start out by hiding everything except the HUD mMap->setVisible(false); mMenu->setVisible(false); @@ -1148,7 +1163,7 @@ namespace MWGui bool WindowManager::isGuiMode() const { - return !mGuiModes.empty() || mMessageBoxManager->isInteractiveMessageBox(); + return !mGuiModes.empty() || (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); } bool WindowManager::isConsoleMode() const @@ -1211,7 +1226,8 @@ namespace MWGui void WindowManager::showCrosshair (bool show) { - mHud->setCrosshairVisible (show && mCrosshairEnabled); + if (mHud) + mHud->setCrosshairVisible (show && mCrosshairEnabled); } void WindowManager::activateQuickKey (int index) @@ -1230,15 +1246,6 @@ namespace MWGui mHud->setVisible (mHudEnabled); } - void WindowManager::setLoadingProgress (const std::string& stage, int depth, int current, int total) - { - mLoadingScreen->setLoadingProgress (stage, depth, current, total); - } - - void WindowManager::loadingDone () - { - mLoadingScreen->loadingDone (); - } bool WindowManager::getRestEnabled() { //Enable rest dialogue if character creation finished @@ -1345,4 +1352,9 @@ namespace MWGui mHud->setEnemy(enemy); } + Loading::Listener* WindowManager::getLoadingScreen() + { + return mLoadingScreen; + } + } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index e49b336479..badb333a7f 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -91,6 +91,11 @@ namespace MWGui Translation::Storage& translationDataStorage, ToUTF8::FromType encoding); virtual ~WindowManager(); + void initUI(); + void renderWorldMap(); + + virtual Loading::Listener* getLoadingScreen(); + /** * Should be called each frame to update windows/gui elements. * This could mean updating sizes of gui elements or opening @@ -241,9 +246,6 @@ namespace MWGui virtual void executeInConsole (const std::string& path); - virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total); - virtual void loadingDone(); - virtual void enableRest() { mRestAllowed = true; } virtual bool getRestEnabled(); @@ -275,6 +277,8 @@ namespace MWGui void onSoulgemDialogButtonPressed (int button); private: + bool mConsoleOnlyScripts; + OEngine::GUI::MyGUIManager *mGuiManager; OEngine::Render::OgreRenderer *mRendering; HUD *mHud; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 573fe389ca..1039a0dced 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -86,13 +86,10 @@ namespace namespace MWInput { InputManager::InputManager(OEngine::Render::OgreRenderer &ogre, - MWWorld::Player& player, - MWBase::WindowManager &windows, OMW::Engine& engine, const std::string& userFile, bool userFileExists) : mOgre(ogre) - , mPlayer(player) - , mWindows(windows) + , mPlayer(NULL) , mEngine(engine) , mMouseLookEnabled(true) , mMouseX(ogre.getWindow()->getWidth ()/2.f) @@ -124,8 +121,6 @@ namespace MWInput adjustMouseRegion (window->getWidth(), window->getHeight()); - MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, 0); - loadKeyDefaults(); for (int i = 0; i < A_Last; ++i) @@ -140,8 +135,6 @@ namespace MWInput mControlSwitch["playermagic"] = true; mControlSwitch["playerviewswitch"] = true; mControlSwitch["vanitymode"] = true; - - changeInputMode(false); } InputManager::~InputManager() @@ -164,7 +157,7 @@ namespace MWInput if (action == A_Use) { - MWWorld::Class::get(mPlayer.getPlayer()).getCreatureStats(mPlayer.getPlayer()).setAttackingOrSpell(currentValue); + MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue); if (currentValue == 1) { int type = MWMechanics::CreatureStats::AT_Chop; @@ -177,7 +170,7 @@ namespace MWInput if (forward && !side) type = MWMechanics::CreatureStats::AT_Thrust; - MWWorld::Class::get(mPlayer.getPlayer()).getCreatureStats(mPlayer.getPlayer()).setAttackType(type); + MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackType(type); } } @@ -204,9 +197,9 @@ namespace MWInput case A_Activate: resetIdleTime(); - if (mWindows.isGuiMode()) + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) { - if (mWindows.getMode() == MWGui::GM_Container) + if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container) toggleContainer (); else MWBase::Environment::get().getWindowManager()->activateKeyPressed(); @@ -266,7 +259,7 @@ namespace MWInput showQuickKeysMenu(); break; case A_ToggleHUD: - mWindows.toggleHud(); + MWBase::Environment::get().getWindowManager()->toggleHud(); break; } } @@ -274,8 +267,7 @@ namespace MWInput void InputManager::update(float dt, bool loading) { - // Tell OIS to handle all input events - mInputManager->capture(); + mInputManager->capture(loading); // inject some fake mouse movement to force updating MyGUI's widget states // this shouldn't do any harm since we're moving back to the original position afterwards MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX+1), int(mMouseY+1), mMouseWheel); @@ -285,18 +277,10 @@ namespace MWInput if (!loading) mInputBinder->update(dt); - // Update windows/gui as a result of input events - // For instance this could mean opening a new window/dialog, - // by doing this after the input events are handled we - // ensure that window/gui changes appear quickly while - // avoiding that window/gui changes does not happen in - // event callbacks (which may crash) - mWindows.update(); - - bool main_menu = mWindows.containsMode(MWGui::GM_MainMenu); + bool main_menu = MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu); bool was_relative = mInputManager->getMouseRelative(); - bool is_relative = !mWindows.isGuiMode(); + bool is_relative = !MWBase::Environment::get().getWindowManager()->isGuiMode(); // don't keep the pointer away from the window edge in gui mode // stop using raw mouse motions and switch to system cursor movements @@ -312,8 +296,11 @@ namespace MWInput mInputManager->warpMouse(mMouseX, mMouseY); } + if (loading) + return; + // Disable movement in Gui mode - if (mWindows.isGuiMode()) return; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; // Configure player movement according to keyboard input. Actual movement will @@ -324,45 +311,45 @@ namespace MWInput if (actionIsActive(A_MoveLeft)) { triedToMove = true; - mPlayer.setLeftRight (-1); + mPlayer->setLeftRight (-1); } else if (actionIsActive(A_MoveRight)) { triedToMove = true; - mPlayer.setLeftRight (1); + mPlayer->setLeftRight (1); } if (actionIsActive(A_MoveForward)) { triedToMove = true; - mPlayer.setAutoMove (false); - mPlayer.setForwardBackward (1); + mPlayer->setAutoMove (false); + mPlayer->setForwardBackward (1); } else if (actionIsActive(A_MoveBackward)) { triedToMove = true; - mPlayer.setAutoMove (false); - mPlayer.setForwardBackward (-1); + mPlayer->setAutoMove (false); + mPlayer->setForwardBackward (-1); } - else if(mPlayer.getAutoMove()) + else if(mPlayer->getAutoMove()) { triedToMove = true; - mPlayer.setForwardBackward (1); + mPlayer->setForwardBackward (1); } - mPlayer.setSneak(actionIsActive(A_Sneak)); + mPlayer->setSneak(actionIsActive(A_Sneak)); if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"]) { - mPlayer.setUpDown (1); + mPlayer->setUpDown (1); triedToMove = true; } if (mAlwaysRunActive) - mPlayer.setRunState(!actionIsActive(A_Run)); + mPlayer->setRunState(!actionIsActive(A_Run)); else - mPlayer.setRunState(actionIsActive(A_Run)); + mPlayer->setRunState(actionIsActive(A_Run)); // if player tried to start moving, but can't (due to being overencumbered), display a notification. if (triedToMove) @@ -371,7 +358,7 @@ namespace MWInput mOverencumberedMessageDelay -= dt; if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player)) { - mPlayer.setAutoMove (false); + mPlayer->setAutoMove (false); if (mOverencumberedMessageDelay <= 0) { MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}"); @@ -425,8 +412,8 @@ namespace MWInput mGuiCursorEnabled = guiMode; mMouseLookEnabled = !guiMode; if (guiMode) - mWindows.showCrosshair(false); - mWindows.setCursorVisible(guiMode); + MWBase::Environment::get().getWindowManager()->showCrosshair(false); + MWBase::Environment::get().getWindowManager()->setCursorVisible(guiMode); // if not in gui mode, the camera decides whether to show crosshair or not. } @@ -459,13 +446,13 @@ namespace MWInput } /// \note 7 switches at all, if-else is relevant if (sw == "playercontrols" && !value) { - mPlayer.setLeftRight(0); - mPlayer.setForwardBackward(0); - mPlayer.setAutoMove(false); - mPlayer.setUpDown(0); + mPlayer->setLeftRight(0); + mPlayer->setForwardBackward(0); + mPlayer->setAutoMove(false); + mPlayer->setUpDown(0); } else if (sw == "playerjumping" && !value) { /// \fixme maybe crouching at this time - mPlayer.setUpDown(0); + mPlayer->setUpDown(0); } else if (sw == "vanitymode") { MWBase::Environment::get().getWorld()->allowVanityMode(value); } else if (sw == "playerlooking") { @@ -594,8 +581,8 @@ namespace MWInput // Only actually turn player when we're not in vanity mode if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot)) { - mPlayer.yaw(x/scale); - mPlayer.pitch(-y/scale); + mPlayer->yaw(x/scale); + mPlayer->pitch(-y/scale); } if (arg.zrel) @@ -627,51 +614,51 @@ namespace MWInput if (MyGUI::InputManager::getInstance ().isModalAny()) return; - if (mWindows.isGuiMode () && mWindows.getMode () == MWGui::GM_Video) + if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video) MWBase::Environment::get().getWorld ()->stopVideo (); - else if (mWindows.containsMode(MWGui::GM_MainMenu)) - mWindows.popGuiMode(); + else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) + MWBase::Environment::get().getWindowManager()->popGuiMode(); else - mWindows.pushGuiMode (MWGui::GM_MainMenu); + MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); } void InputManager::toggleSpell() { - if (mWindows.isGuiMode()) return; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; // Not allowed before the magic window is accessible - if (!mWindows.isAllowed(MWGui::GW_Magic)) + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic)) return; - MWMechanics::DrawState_ state = mPlayer.getDrawState(); + MWMechanics::DrawState_ state = mPlayer->getDrawState(); if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing) - mPlayer.setDrawState(MWMechanics::DrawState_Spell); + mPlayer->setDrawState(MWMechanics::DrawState_Spell); else - mPlayer.setDrawState(MWMechanics::DrawState_Nothing); + mPlayer->setDrawState(MWMechanics::DrawState_Nothing); } void InputManager::toggleWeapon() { - if (mWindows.isGuiMode()) return; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; // Not allowed before the inventory window is accessible - if (!mWindows.isAllowed(MWGui::GW_Inventory)) + if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) return; - MWMechanics::DrawState_ state = mPlayer.getDrawState(); + MWMechanics::DrawState_ state = mPlayer->getDrawState(); if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing) - mPlayer.setDrawState(MWMechanics::DrawState_Weapon); + mPlayer->setDrawState(MWMechanics::DrawState_Weapon); else - mPlayer.setDrawState(MWMechanics::DrawState_Nothing); + mPlayer->setDrawState(MWMechanics::DrawState_Nothing); } void InputManager::rest() { - if (!mWindows.getRestEnabled () || mWindows.isGuiMode ()) + if (!MWBase::Environment::get().getWindowManager()->getRestEnabled () || MWBase::Environment::get().getWindowManager()->isGuiMode ()) return; /// \todo check if resting is currently allowed (enemies nearby?) - mWindows.pushGuiMode (MWGui::GM_Rest); + MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest); } void InputManager::screenshot() @@ -679,7 +666,7 @@ namespace MWInput mEngine.screenshot(); std::vector empty; - mWindows.messageBox ("Screenshot saved", empty); + MWBase::Environment::get().getWindowManager()->messageBox ("Screenshot saved", empty); } void InputManager::toggleInventory() @@ -688,13 +675,13 @@ namespace MWInput return; // Toggle between game mode and inventory mode - if(!mWindows.isGuiMode()) - mWindows.pushGuiMode(MWGui::GM_Inventory); + if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Inventory); else { - MWGui::GuiMode mode = mWindows.getMode(); + MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode(); if(mode == MWGui::GM_Inventory || mode == MWGui::GM_Container) - mWindows.popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } // .. but don't touch any other mode, except container. @@ -705,12 +692,12 @@ namespace MWInput if (MyGUI::InputManager::getInstance ().isModalAny()) return; - if(mWindows.isGuiMode()) + if(MWBase::Environment::get().getWindowManager()->isGuiMode()) { - if (mWindows.getMode() == MWGui::GM_Container) - mWindows.popGuiMode(); + if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container) + MWBase::Environment::get().getWindowManager()->popGuiMode(); else - mWindows.pushGuiMode(MWGui::GM_Container); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container); } } @@ -722,15 +709,15 @@ namespace MWInput // Switch to console mode no matter what mode we are currently // in, except of course if we are already in console mode - if (mWindows.isGuiMode()) + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) { - if (mWindows.getMode() == MWGui::GM_Console) - mWindows.popGuiMode(); + if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console) + MWBase::Environment::get().getWindowManager()->popGuiMode(); else - mWindows.pushGuiMode(MWGui::GM_Console); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console); } else - mWindows.pushGuiMode(MWGui::GM_Console); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console); } void InputManager::toggleJournal() @@ -739,31 +726,31 @@ namespace MWInput return; // Toggle between game mode and journal mode - if(!mWindows.isGuiMode() && MWBase::Environment::get().getWindowManager ()->getJournalAllowed()) + if(!MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager ()->getJournalAllowed()) { MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0); - mWindows.pushGuiMode(MWGui::GM_Journal); + MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Journal); } - else if(mWindows.getMode() == MWGui::GM_Journal) + else if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Journal) { MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - mWindows.popGuiMode(); + MWBase::Environment::get().getWindowManager()->popGuiMode(); } // .. but don't touch any other mode. } void InputManager::quickKey (int index) { - if (!mWindows.isGuiMode()) - mWindows.activateQuickKey (index); + if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) + MWBase::Environment::get().getWindowManager()->activateQuickKey (index); } void InputManager::showQuickKeysMenu() { - if (!mWindows.isGuiMode ()) - mWindows.pushGuiMode (MWGui::GM_QuickKeysMenu); - else if (mWindows.getMode () == MWGui::GM_QuickKeysMenu) - mWindows.removeGuiMode (MWGui::GM_QuickKeysMenu); + if (!MWBase::Environment::get().getWindowManager()->isGuiMode ()) + MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_QuickKeysMenu); + else if (MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_QuickKeysMenu) + MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_QuickKeysMenu); } void InputManager::activate() @@ -774,22 +761,22 @@ namespace MWInput void InputManager::toggleAutoMove() { - if (mWindows.isGuiMode()) return; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; if (mControlSwitch["playercontrols"]) - mPlayer.setAutoMove (!mPlayer.getAutoMove()); + mPlayer->setAutoMove (!mPlayer->getAutoMove()); } void InputManager::toggleWalking() { - if (mWindows.isGuiMode()) return; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; mAlwaysRunActive = !mAlwaysRunActive; } // Exit program now button (which is disabled in GUI mode) void InputManager::exitNow() { - if(!mWindows.isGuiMode()) + if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) Ogre::Root::getSingleton().queueEndRendering (); } diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index ef7ef75a89..5f9a752d72 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -60,8 +60,6 @@ namespace MWInput { public: InputManager(OEngine::Render::OgreRenderer &_ogre, - MWWorld::Player&_player, - MWBase::WindowManager &_windows, OMW::Engine& engine, const std::string& userFile, bool userFileExists); @@ -69,6 +67,8 @@ namespace MWInput virtual void update(float dt, bool loading); + void setPlayer (MWWorld::Player* player) { mPlayer = player; } + virtual void changeInputMode(bool guiMode); virtual void processChangedSettings(const Settings::CategorySettingVector& changed); @@ -125,8 +125,7 @@ namespace MWInput private: OEngine::Render::OgreRenderer &mOgre; - MWWorld::Player& mPlayer; - MWBase::WindowManager &mWindows; + MWWorld::Player* mPlayer; OMW::Engine& mEngine; ICS::InputControlSystem* mInputBinder; diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 78b13ec07e..120a83fae7 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -28,7 +30,7 @@ namespace MWRender } - void GlobalMap::render () + void GlobalMap::render (Loading::Listener* loadingListener) { Ogre::TexturePtr tex; @@ -53,6 +55,11 @@ namespace MWRender mWidth = cellSize*(mMaxX-mMinX+1); mHeight = cellSize*(mMaxY-mMinY+1); + loadingListener->loadingOn(); + loadingListener->setLabel("Creating map"); + loadingListener->setProgressRange((mMaxX-mMinX+1) * (mMaxY-mMinY+1)); + loadingListener->setProgress(0); + mExploredBuffer.resize((mMaxX-mMinX+1) * (mMaxY-mMinY+1) * 4); //if (!boost::filesystem::exists(mCacheDir + "/GlobalMap.png")) @@ -147,6 +154,7 @@ namespace MWRender data[texelY * mWidth * 3 + texelX * 3+2] = b; } } + loadingListener->increaseProgress(1); } } @@ -177,6 +185,8 @@ namespace MWRender memcpy(mOverlayTexture->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], mWidth*mHeight*4); mOverlayTexture->getBuffer()->unlock(); + + loadingListener->loadingOff(); } void GlobalMap::worldPosToImageSpace(float x, float z, float& imageX, float& imageY) diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index c01182c5b5..dd3787b62b 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -5,6 +5,11 @@ #include +namespace Loading +{ + class Listener; +} + namespace MWRender { @@ -13,7 +18,7 @@ namespace MWRender public: GlobalMap(const std::string& cacheDir); - void render(); + void render(Loading::Listener* loadingListener); int getWidth() { return mWidth; } int getHeight() { return mHeight; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a7e35fa195..d6887fe6d8 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -82,7 +82,7 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b Settings::Manager::setString("shader mode", "General", openGL ? (glES ? "glsles" : "glsl") : "hlsl"); } - mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); + mRendering.adjustCamera(Settings::Manager::getFloat("field of view", "General"), 5); mRendering.getWindow()->addListener(this); mRendering.setWindowListener(this); @@ -1018,12 +1018,15 @@ void RenderingManager::enableTerrain(bool enable) { if (!mTerrain) { - mTerrain = new Terrain::Terrain(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain, + Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); + Loading::ScopedLoad load(listener); + mTerrain = new Terrain::Terrain(listener, mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain, Settings::Manager::getBool("distant land", "Terrain"), Settings::Manager::getBool("shader", "Terrain")); mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"), Settings::Manager::getBool("split", "Shadows")); mTerrain->update(mRendering.getCamera()->getRealPosition()); + mTerrain->setLoadingListener(NULL); } mTerrain->setVisible(true); } diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 5a4f1db541..7703f2d233 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -5,6 +5,8 @@ #include +#include + namespace MWWorld { @@ -21,8 +23,10 @@ static bool isCacheableRecord(int id) return false; } -void ESMStore::load(ESM::ESMReader &esm) +void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener) { + listener->setProgressRange(1000); + std::set missing; ESM::Dialogue *dialogue = 0; @@ -109,6 +113,7 @@ void ESMStore::load(ESM::ESMReader &esm) mIds[id] = n.val; } } + listener->setProgress(esm.getFileOffset() / (float)esm.getFileSize() * 1000); } /* This information isn't needed on screen. But keep the code around diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index d86faf7663..ebb086cee5 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -6,6 +6,11 @@ #include #include "store.hpp" +namespace Loading +{ + class Listener; +} + namespace MWWorld { class ESMStore @@ -158,7 +163,7 @@ namespace MWWorld mNpcs.insert(mPlayerTemplate); } - void load(ESM::ESMReader &esm); + void load(ESM::ESMReader &esm, Loading::Listener* listener); template const Store &get() const { diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index ee8973ae53..0c98ca504f 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -25,13 +25,12 @@ namespace template void insertCellRefList(MWRender::RenderingManager& rendering, - T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics, bool rescale) + T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics, bool rescale, Loading::Listener* loadingListener) { if (!cellRefList.mList.empty()) { const MWWorld::Class& class_ = MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.mList.begin(), &cell)); - int current = 0; for (typename T::List::iterator it = cellRefList.mList.begin(); it != cellRefList.mList.end(); it++) { @@ -43,8 +42,6 @@ namespace it->mRef.mScale = 2; } - ++current; - if (it->mData.getCount() && it->mData.isEnabled()) { MWWorld::Ptr ptr (&*it, &cell); @@ -68,6 +65,8 @@ namespace std::cerr << error + e.what() << std::endl; } } + + loadingListener->increaseProgress(1); } } } @@ -117,7 +116,7 @@ namespace MWWorld mActiveCells.erase(*iter); } - void Scene::loadCell (Ptr::CellStore *cell) + void Scene::loadCell (Ptr::CellStore *cell, Loading::Listener* loadingListener) { // register local scripts MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell); @@ -150,7 +149,7 @@ namespace MWWorld // ... then references. This is important for adjustPosition to work correctly. /// \todo rescale depending on the state of a new GMST - insertCell (*cell, true); + insertCell (*cell, true, loadingListener); mRendering.cellAdded (cell); @@ -200,17 +199,15 @@ namespace MWWorld void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) { Nif::NIFFile::CacheLock cachelock; - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - mRendering.preCellChange(mCurrentCell); + Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); + Loading::ScopedLoad load(loadingListener); // remove active MWBase::Environment::get().getMechanicsManager()->remove(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - std::string loadingExteriorText; - - loadingExteriorText = gmst.find ("sLoadingMessage3")->getString(); + std::string loadingExteriorText = "#{sLoadingMessage3}"; + loadingListener->setLabel(loadingExteriorText); CellStoreCollection::iterator active = mActiveCells.begin(); @@ -232,7 +229,6 @@ namespace MWWorld ++numUnload; } - int current = 0; active = mActiveCells.begin(); while (active!=mActiveCells.end()) { @@ -247,11 +243,10 @@ namespace MWWorld } } unloadCell (active++); - ++current; } - int numLoad = 0; - // get the number of cells to load + int refsToLoad = 0; + // get the number of refs to load for (int x=X-1; x<=X+1; ++x) for (int y=Y-1; y<=Y+1; ++y) { @@ -269,11 +264,12 @@ namespace MWWorld } if (iter==mActiveCells.end()) - ++numLoad; + refsToLoad += countRefs(*MWBase::Environment::get().getWorld()->getExterior(x, y)); } + loadingListener->setProgressRange(refsToLoad); + // Load cells - current = 0; for (int x=X-1; x<=X+1; ++x) for (int y=Y-1; y<=Y+1; ++y) { @@ -294,11 +290,7 @@ namespace MWWorld { CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y); - //Loading Exterior loading text - MWBase::Environment::get().getWindowManager ()->setLoadingProgress (loadingExteriorText, 0, current, numLoad); - - loadCell (cell); - ++current; + loadCell (cell, loadingListener); } } @@ -330,7 +322,7 @@ namespace MWWorld mCellChanged = true; - MWBase::Environment::get().getWindowManager ()->loadingDone (); + loadingListener->removeWallpaper(); } //We need the ogre renderer and a scene node. @@ -356,13 +348,14 @@ namespace MWWorld void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.5); - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); mRendering.enableTerrain(false); - std::string loadingInteriorText; - loadingInteriorText = gmst.find ("sLoadingMessage2")->getString(); + Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); + Loading::ScopedLoad load(loadingListener); + + std::string loadingInteriorText = "#{sLoadingMessage2}"; + loadingListener->setLabel(loadingInteriorText); CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName); bool loadcell = (mCurrentCell == NULL); @@ -406,13 +399,15 @@ namespace MWWorld ++current; } + int refsToLoad = countRefs(*cell); + loadingListener->setProgressRange(refsToLoad); + // Load cell. std::cout << "cellName: " << cell->mCell->mName << std::endl; //Loading Interior loading text - MWBase::Environment::get().getWindowManager ()->setLoadingProgress (loadingInteriorText, 0, 0, 1); - loadCell (cell); + loadCell (cell, loadingListener); mCurrentCell = cell; @@ -429,7 +424,7 @@ namespace MWWorld mCellChanged = true; MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.5); - MWBase::Environment::get().getWindowManager ()->loadingDone (); + loadingListener->removeWallpaper(); } void Scene::changeToExteriorCell (const ESM::Position& position) @@ -454,30 +449,54 @@ namespace MWWorld mCellChanged = false; } - void Scene::insertCell (Ptr::CellStore &cell, bool rescale) + int Scene::countRefs (const Ptr::CellStore& cell) + { + return cell.mActivators.mList.size() + + cell.mPotions.mList.size() + + cell.mAppas.mList.size() + + cell.mArmors.mList.size() + + cell.mBooks.mList.size() + + cell.mClothes.mList.size() + + cell.mContainers.mList.size() + + cell.mDoors.mList.size() + + cell.mIngreds.mList.size() + + cell.mCreatureLists.mList.size() + + cell.mItemLists.mList.size() + + cell.mLights.mList.size() + + cell.mLockpicks.mList.size() + + cell.mMiscItems.mList.size() + + cell.mProbes.mList.size() + + cell.mRepairs.mList.size() + + cell.mStatics.mList.size() + + cell.mWeapons.mList.size() + + cell.mCreatures.mList.size() + + cell.mNpcs.mList.size(); + } + + void Scene::insertCell (Ptr::CellStore &cell, bool rescale, Loading::Listener* loadingListener) { // Loop through all references in the cell - insertCellRefList(mRendering, cell.mActivators, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mPotions, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mAppas, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mArmors, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mItemLists, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mLights, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics, rescale); + insertCellRefList(mRendering, cell.mActivators, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mPotions, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mAppas, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mArmors, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mItemLists, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mLights, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics, rescale, loadingListener); // Load NPCs and creatures _after_ everything else (important for adjustPosition to work correctly) - insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale); - insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale); + insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale, loadingListener); + insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale, loadingListener); } void Scene::addObjectToScene (const Ptr& ptr) diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 3dfbd1045b..e3edad352a 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -56,7 +56,9 @@ namespace MWWorld void playerCellChange (CellStore *cell, const ESM::Position& position, bool adjustPlayerPos = true); - void insertCell (Ptr::CellStore &cell, bool rescale); + void insertCell (Ptr::CellStore &cell, bool rescale, Loading::Listener* loadingListener); + + int countRefs (const Ptr::CellStore& cell); public: @@ -66,7 +68,7 @@ namespace MWWorld void unloadCell (CellStoreCollection::iterator iter); - void loadCell (CellStore *cell); + void loadCell (CellStore *cell, Loading::Listener* loadingListener); void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos); ///< Move from exterior to interior or from interior cell to a different diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 09dc0493e8..eac0a39776 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -184,11 +184,14 @@ namespace MWWorld int idx = 0; // NOTE: We might need to reserve one more for the running game / save. mEsm.resize(master.size() + plugins.size()); + Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); + listener->loadingOn(); for (std::vector::size_type i = 0; i < master.size(); i++, idx++) { boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i])); std::cout << "Loading ESM " << masterPath.string() << "\n"; + listener->setLabel(masterPath.filename().string()); // This parses the ESM file ESM::ESMReader lEsm; @@ -197,7 +200,7 @@ namespace MWWorld lEsm.setGlobalReaderList(&mEsm); lEsm.open (masterPath.string()); mEsm[idx] = lEsm; - mStore.load (mEsm[idx]); + mStore.load (mEsm[idx], listener); } for (std::vector::size_type i = 0; i < plugins.size(); i++, idx++) @@ -205,6 +208,7 @@ namespace MWWorld boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i])); std::cout << "Loading ESP " << pluginPath.string() << "\n"; + listener->setLabel(pluginPath.filename().string()); // This parses the ESP file ESM::ESMReader lEsm; @@ -213,8 +217,9 @@ namespace MWWorld lEsm.setGlobalReaderList(&mEsm); lEsm.open (pluginPath.string()); mEsm[idx] = lEsm; - mStore.load (mEsm[idx]); + mStore.load (mEsm[idx], listener); } + listener->loadingOff(); // insert records that may not be present in all versions of MW if (mEsm[0].getFormat() == 0) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index baf905aa7f..1dd6816acd 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -69,6 +69,10 @@ add_component_dir (translation add_component_dir (terrain quadtreenode chunk terrain storage material ) + +add_component_dir (loadinglistener + loadinglistener + ) find_package(Qt4 COMPONENTS QtCore QtGui) diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index ff10a202c9..edc724cd2a 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -70,6 +70,11 @@ public: void openRaw(const std::string &file); + /// Get the file size. Make sure that the file has been opened! + size_t getFileSize() { return mEsm->size(); } + /// Get the current position in the file. Make sure that the file has been opened! + size_t getFileOffset() { return mEsm->tell(); } + // This is a quick hack for multiple esm/esp files. Each plugin introduces its own // terrain palette, but ESMReader does not pass a reference to the correct plugin // to the individual load() methods. This hack allows to pass this reference diff --git a/components/loadinglistener/loadinglistener.hpp b/components/loadinglistener/loadinglistener.hpp new file mode 100644 index 0000000000..483d524910 --- /dev/null +++ b/components/loadinglistener/loadinglistener.hpp @@ -0,0 +1,35 @@ +#ifndef COMPONENTS_LOADINGLISTENER_H +#define COMPONENTS_LOADINGLISTENER_H + +namespace Loading +{ + class Listener + { + public: + virtual void setLabel (const std::string& label) = 0; + + // Use ScopedLoad instead of using these directly + virtual void loadingOn() = 0; + virtual void loadingOff() = 0; + + /// Indicate that some progress has been made, without specifying how much + virtual void indicateProgress () = 0; + + virtual void setProgressRange (size_t range) = 0; + virtual void setProgress (size_t value) = 0; + virtual void increaseProgress (size_t increase) = 0; + + /// Indicate the scene is now ready to be shown + virtual void removeWallpaper() = 0; + }; + + // Used for stopping a loading sequence when the object goes out of scope + struct ScopedLoad + { + ScopedLoad(Listener* l) : mListener(l) { mListener->loadingOn(); } + ~ScopedLoad() { mListener->loadingOff(); } + Listener* mListener; + }; +} + +#endif diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index ed56738770..e581c40ea1 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -220,7 +220,7 @@ const Ogre::AxisAlignedBox& QuadTreeNode::getBoundingBox() return mBounds; } -void QuadTreeNode::update(const Ogre::Vector3 &cameraPos) +void QuadTreeNode::update(const Ogre::Vector3 &cameraPos, Loading::Listener* loadingListener) { const Ogre::AxisAlignedBox& bounds = getBoundingBox(); if (bounds.isNull()) @@ -254,6 +254,9 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos) bool hadChunk = hasChunk(); + if (loadingListener) + loadingListener->indicateProgress(); + if (!distantLand && dist > 8192*2) { if (mIsActive) @@ -341,7 +344,7 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos) } assert(hasChildren() && "Leaf node's LOD needs to be 0"); for (int i=0; i<4; ++i) - mChildren[i]->update(cameraPos); + mChildren[i]->update(cameraPos, loadingListener); } } diff --git a/components/terrain/quadtreenode.hpp b/components/terrain/quadtreenode.hpp index fe646f3bfd..5adb9676a3 100644 --- a/components/terrain/quadtreenode.hpp +++ b/components/terrain/quadtreenode.hpp @@ -5,6 +5,8 @@ #include #include +#include + namespace Ogre { class Rectangle2D; @@ -96,7 +98,7 @@ namespace Terrain Terrain* getTerrain() { return mTerrain; } /// Adjust LODs for the given camera position, possibly splitting up chunks or merging them. - void update (const Ogre::Vector3& cameraPos); + void update (const Ogre::Vector3& cameraPos, Loading::Listener* loadingListener); /// Adjust index buffers of chunks to stitch together chunks of different LOD, so that cracks are avoided. /// Call after QuadTreeNode::update! diff --git a/components/terrain/terrain.cpp b/components/terrain/terrain.cpp index 1a88d63e44..31a6ff5268 100644 --- a/components/terrain/terrain.cpp +++ b/components/terrain/terrain.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "storage.hpp" #include "quadtreenode.hpp" @@ -51,7 +52,8 @@ namespace namespace Terrain { - Terrain::Terrain(Ogre::SceneManager* sceneMgr, Storage* storage, int visibilityFlags, bool distantLand, bool shaders) + Terrain::Terrain(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr, + Storage* storage, int visibilityFlags, bool distantLand, bool shaders) : mStorage(storage) , mMinBatchSize(1) , mMaxBatchSize(64) @@ -60,7 +62,10 @@ namespace Terrain , mDistantLand(distantLand) , mShaders(shaders) , mVisible(true) + , mLoadingListener(loadingListener) { + loadingListener->setLabel("Creating terrain"); + mCompositeMapSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); Ogre::Camera* compositeMapCam = mCompositeMapSceneMgr->createCamera("a"); @@ -86,8 +91,11 @@ namespace Terrain mRootNode = new QuadTreeNode(this, Root, size, Ogre::Vector2(center.x, center.y), NULL); buildQuadTree(mRootNode); + loadingListener->indicateProgress(); mRootNode->initAabb(); + loadingListener->indicateProgress(); mRootNode->initNeighbours(); + loadingListener->indicateProgress(); } Terrain::~Terrain() @@ -147,7 +155,7 @@ namespace Terrain { if (!mVisible) return; - mRootNode->update(cameraPos); + mRootNode->update(cameraPos, mLoadingListener); mRootNode->updateIndexBuffers(); } diff --git a/components/terrain/terrain.hpp b/components/terrain/terrain.hpp index 4d329f9e19..ad829cb478 100644 --- a/components/terrain/terrain.hpp +++ b/components/terrain/terrain.hpp @@ -6,6 +6,11 @@ #include #include +namespace Loading +{ + class Listener; +} + namespace Ogre { class Camera; @@ -28,6 +33,7 @@ namespace Terrain { public: /// @note takes ownership of \a storage + /// @param loadingListener Listener to update with progress /// @param sceneMgr scene manager to use /// @param storage Storage instance to get terrain data from (heights, normals, colors, textures..) /// @param visbilityFlags visibility flags for the created meshes @@ -35,9 +41,12 @@ namespace Terrain /// This is a temporary option until it can be streamlined. /// @param shaders Whether to use splatting shader, or multi-pass fixed function splatting. Shader is usually /// faster so this is just here for compatibility. - Terrain(Ogre::SceneManager* sceneMgr, Storage* storage, int visiblityFlags, bool distantLand, bool shaders); + Terrain(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr, + Storage* storage, int visiblityFlags, bool distantLand, bool shaders); ~Terrain(); + void setLoadingListener(Loading::Listener* loadingListener) { mLoadingListener = loadingListener; } + bool getDistantLandEnabled() { return mDistantLand; } bool getShadersEnabled() { return mShaders; } bool getShadowsEnabled() { return mShadows; } @@ -84,6 +93,8 @@ namespace Terrain bool mSplitShadows; bool mVisible; + Loading::Listener* mLoadingListener; + QuadTreeNode* mRootNode; Ogre::SceneNode* mRootSceneNode; Storage* mStorage; diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index 5602946ff1..931d6aca30 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -35,9 +35,20 @@ namespace SFO mSDLWindow = NULL; } - void InputWrapper::capture() + void InputWrapper::capture(bool windowEventsOnly) { + SDL_PumpEvents(); + SDL_Event evt; + + if (windowEventsOnly) + { + // During loading, just handle window events, and keep others for later + while (SDL_PeepEvents(&evt, 1, SDL_GETEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT)) + handleWindowEvent(evt); + return; + } + while(SDL_PollEvent(&evt)) { switch(evt.type) diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp index 66bf60c7c3..1bd8947a0d 100644 --- a/extern/sdl4ogre/sdlinputwrapper.hpp +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -24,7 +24,7 @@ namespace SFO void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; } void setJoyEventCallback(JoyListener* listen) { mJoyListener = listen; } - void capture(); + void capture(bool windowEventsOnly); bool isModifierHeld(SDL_Keymod mod); bool isKeyDown(SDL_Scancode key); diff --git a/files/mygui/openmw_loading_screen.layout b/files/mygui/openmw_loading_screen.layout index 1e4bba5ed8..5fd3440f91 100644 --- a/files/mygui/openmw_loading_screen.layout +++ b/files/mygui/openmw_loading_screen.layout @@ -12,8 +12,7 @@ - - + diff --git a/files/mygui/openmw_progress.skin.xml b/files/mygui/openmw_progress.skin.xml index aa994fea7a..35114ffebb 100644 --- a/files/mygui/openmw_progress.skin.xml +++ b/files/mygui/openmw_progress.skin.xml @@ -58,10 +58,23 @@ - + + + + + + + + + + + + + + diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 0834a2cd16..9127812408 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -279,27 +279,23 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& 0, Ogre::PF_A8R8G8B8, Ogre::TU_WRITE_ONLY); -} -void OgreRenderer::createScene(const std::string& camName, float fov, float nearClip) -{ - assert(mRoot); - assert(mWindow); - // Get the SceneManager, in this case a generic one mScene = mRoot->createSceneManager(ST_GENERIC); - // Create the camera - mCamera = mScene->createCamera(camName); - mCamera->setNearClipDistance(nearClip); - mCamera->setFOVy(Degree(fov)); + mFader = new Fader(mScene); + + mCamera = mScene->createCamera("cam"); // Create one viewport, entire window mView = mWindow->addViewport(mCamera); - // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); +} - mFader = new Fader(mScene); +void OgreRenderer::adjustCamera(float fov, float nearClip) +{ + mCamera->setNearClipDistance(nearClip); + mCamera->setFOVy(Degree(fov)); } void OgreRenderer::adjustViewport() diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 9e83bf4f67..89edc567dd 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -157,7 +157,7 @@ namespace OEngine void createWindow(const std::string &title, const WindowSettings& settings); /// Set up the scene manager, camera and viewport - void createScene(const std::string& camName="Camera",// Camera name + void adjustCamera( float fov=55, // Field of view angle float nearClip=5 // Near clip distance ); From 839d251cc5b763e89ca0f5dc23a05bcf65a05885 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 Aug 2013 16:01:16 +0200 Subject: [PATCH 22/40] Renamed Terrain::Terrain to Terrain::World to make VC happy --- apps/openmw/mwrender/renderingmanager.cpp | 4 +-- apps/openmw/mwrender/renderingmanager.hpp | 4 +-- components/CMakeLists.txt | 2 +- components/terrain/chunk.cpp | 2 +- components/terrain/quadtreenode.cpp | 4 +-- components/terrain/quadtreenode.hpp | 8 ++--- components/terrain/{terrain.cpp => world.cpp} | 29 ++++++++++--------- components/terrain/{terrain.hpp => world.hpp} | 6 ++-- 8 files changed, 30 insertions(+), 29 deletions(-) rename components/terrain/{terrain.cpp => world.cpp} (94%) rename components/terrain/{terrain.hpp => world.hpp} (97%) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index d6887fe6d8..e03b2ccfcf 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include "../mwworld/esmstore.hpp" #include "../mwworld/class.hpp" @@ -1020,7 +1020,7 @@ void RenderingManager::enableTerrain(bool enable) { Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); Loading::ScopedLoad load(listener); - mTerrain = new Terrain::Terrain(listener, mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain, + mTerrain = new Terrain::World(listener, mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain, Settings::Manager::getBool("distant land", "Terrain"), Settings::Manager::getBool("shader", "Terrain")); mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"), diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 45929f0640..2d08139128 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -40,7 +40,7 @@ namespace sh namespace Terrain { - class Terrain; + class World; } namespace MWRender @@ -234,7 +234,7 @@ private: OcclusionQuery* mOcclusionQuery; - Terrain::Terrain* mTerrain; + Terrain::World* mTerrain; MWRender::Water *mWater; diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 1dd6816acd..04423dc6f0 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -67,7 +67,7 @@ add_component_dir (translation ) add_component_dir (terrain - quadtreenode chunk terrain storage material + quadtreenode chunk world storage material ) add_component_dir (loadinglistener diff --git a/components/terrain/chunk.cpp b/components/terrain/chunk.cpp index 87222af8b8..ce2118cdbd 100644 --- a/components/terrain/chunk.cpp +++ b/components/terrain/chunk.cpp @@ -4,7 +4,7 @@ #include #include "quadtreenode.hpp" -#include "terrain.hpp" +#include "world.hpp" #include "storage.hpp" namespace Terrain diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index e581c40ea1..95daa0afbc 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -3,7 +3,7 @@ #include #include -#include "terrain.hpp" +#include "world.hpp" #include "chunk.hpp" #include "storage.hpp" @@ -132,7 +132,7 @@ namespace } } -QuadTreeNode::QuadTreeNode(Terrain* terrain, ChildDirection dir, float size, const Ogre::Vector2 ¢er, QuadTreeNode* parent) +QuadTreeNode::QuadTreeNode(World* terrain, ChildDirection dir, float size, const Ogre::Vector2 ¢er, QuadTreeNode* parent) : mSize(size) , mCenter(center) , mParent(parent) diff --git a/components/terrain/quadtreenode.hpp b/components/terrain/quadtreenode.hpp index 5adb9676a3..9f6fb5d242 100644 --- a/components/terrain/quadtreenode.hpp +++ b/components/terrain/quadtreenode.hpp @@ -14,7 +14,7 @@ namespace Ogre namespace Terrain { - class Terrain; + class World; class Chunk; class MaterialGenerator; @@ -48,7 +48,7 @@ namespace Terrain /// @param size size (in *cell* units!) /// @param center center (in *cell* units!) /// @param parent parent node - QuadTreeNode (Terrain* terrain, ChildDirection dir, float size, const Ogre::Vector2& center, QuadTreeNode* parent); + QuadTreeNode (World* terrain, ChildDirection dir, float size, const Ogre::Vector2& center, QuadTreeNode* parent); ~QuadTreeNode(); void setVisible(bool visible); @@ -95,7 +95,7 @@ namespace Terrain /// Get bounding box in local coordinates const Ogre::AxisAlignedBox& getBoundingBox(); - Terrain* getTerrain() { return mTerrain; } + World* getTerrain() { return mTerrain; } /// Adjust LODs for the given camera position, possibly splitting up chunks or merging them. void update (const Ogre::Vector3& cameraPos, Loading::Listener* loadingListener); @@ -148,7 +148,7 @@ namespace Terrain Chunk* mChunk; - Terrain* mTerrain; + World* mTerrain; Ogre::TexturePtr mCompositeMap; diff --git a/components/terrain/terrain.cpp b/components/terrain/world.cpp similarity index 94% rename from components/terrain/terrain.cpp rename to components/terrain/world.cpp index 31a6ff5268..711ebbc8fa 100644 --- a/components/terrain/terrain.cpp +++ b/components/terrain/world.cpp @@ -1,4 +1,4 @@ -#include "terrain.hpp" +#include "world.hpp" #include #include @@ -52,7 +52,7 @@ namespace namespace Terrain { - Terrain::Terrain(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr, + World::World(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr, Storage* storage, int visibilityFlags, bool distantLand, bool shaders) : mStorage(storage) , mMinBatchSize(1) @@ -65,6 +65,7 @@ namespace Terrain , mLoadingListener(loadingListener) { loadingListener->setLabel("Creating terrain"); + loadingListener->indicateProgress(); mCompositeMapSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); @@ -98,13 +99,13 @@ namespace Terrain loadingListener->indicateProgress(); } - Terrain::~Terrain() + World::~World() { delete mRootNode; delete mStorage; } - void Terrain::buildQuadTree(QuadTreeNode *node) + void World::buildQuadTree(QuadTreeNode *node) { float halfSize = node->getSize()/2.f; @@ -151,7 +152,7 @@ namespace Terrain node->markAsDummy(); } - void Terrain::update(const Ogre::Vector3& cameraPos) + void World::update(const Ogre::Vector3& cameraPos) { if (!mVisible) return; @@ -159,7 +160,7 @@ namespace Terrain mRootNode->updateIndexBuffers(); } - Ogre::AxisAlignedBox Terrain::getWorldBoundingBox (const Ogre::Vector2& center) + Ogre::AxisAlignedBox World::getWorldBoundingBox (const Ogre::Vector2& center) { if (center.x > mBounds.getMaximum().x || center.x < mBounds.getMinimum().x @@ -173,7 +174,7 @@ namespace Terrain return box; } - Ogre::HardwareVertexBufferSharedPtr Terrain::getVertexBuffer(int numVertsOneSide) + Ogre::HardwareVertexBufferSharedPtr World::getVertexBuffer(int numVertsOneSide) { if (mUvBufferMap.find(numVertsOneSide) != mUvBufferMap.end()) { @@ -205,7 +206,7 @@ namespace Terrain return buffer; } - Ogre::HardwareIndexBufferSharedPtr Terrain::getIndexBuffer(int flags, size_t& numIndices) + Ogre::HardwareIndexBufferSharedPtr World::getIndexBuffer(int flags, size_t& numIndices) { if (mIndexBufferMap.find(flags) != mIndexBufferMap.end()) { @@ -366,31 +367,31 @@ namespace Terrain return buffer; } - void Terrain::renderCompositeMap(Ogre::TexturePtr target) + void World::renderCompositeMap(Ogre::TexturePtr target) { mCompositeMapRenderTarget->update(); target->getBuffer()->blit(mCompositeMapRenderTexture->getBuffer()); } - void Terrain::clearCompositeMapSceneManager() + void World::clearCompositeMapSceneManager() { mCompositeMapSceneMgr->destroyAllManualObjects(); mCompositeMapSceneMgr->clearScene(); } - float Terrain::getHeightAt(const Ogre::Vector3 &worldPos) + float World::getHeightAt(const Ogre::Vector3 &worldPos) { return mStorage->getHeightAt(worldPos); } - void Terrain::applyMaterials(bool shadows, bool splitShadows) + void World::applyMaterials(bool shadows, bool splitShadows) { mShadows = shadows; mSplitShadows = splitShadows; mRootNode->applyMaterials(); } - void Terrain::setVisible(bool visible) + void World::setVisible(bool visible) { if (visible && !mVisible) mSceneMgr->getRootSceneNode()->addChild(mRootSceneNode); @@ -400,7 +401,7 @@ namespace Terrain mVisible = visible; } - bool Terrain::getVisible() + bool World::getVisible() { return mVisible; } diff --git a/components/terrain/terrain.hpp b/components/terrain/world.hpp similarity index 97% rename from components/terrain/terrain.hpp rename to components/terrain/world.hpp index ad829cb478..b8c1b0a7d6 100644 --- a/components/terrain/terrain.hpp +++ b/components/terrain/world.hpp @@ -29,7 +29,7 @@ namespace Terrain * Cracks at LOD transitions are avoided using stitching. * @note Multiple cameras are not supported yet */ - class Terrain + class World { public: /// @note takes ownership of \a storage @@ -41,9 +41,9 @@ namespace Terrain /// This is a temporary option until it can be streamlined. /// @param shaders Whether to use splatting shader, or multi-pass fixed function splatting. Shader is usually /// faster so this is just here for compatibility. - Terrain(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr, + World(Loading::Listener* loadingListener, Ogre::SceneManager* sceneMgr, Storage* storage, int visiblityFlags, bool distantLand, bool shaders); - ~Terrain(); + ~World(); void setLoadingListener(Loading::Listener* loadingListener) { mLoadingListener = loadingListener; } From 188df341c3e403052557d771125f07a314afd51d Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 Aug 2013 16:08:58 +0200 Subject: [PATCH 23/40] Replaced log2 to make VC happy --- components/terrain/quadtreenode.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index 95daa0afbc..ef2c610138 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -13,6 +13,13 @@ using namespace Terrain; namespace { + int Log2( int n ) + { + assert(n > 0); + int targetlevel = 0; + while (n >>= 1) ++targetlevel; + return targetlevel; + } // Utility functions for neighbour finding algorithm ChildDirection reflect(ChildDirection dir, Direction dir2) @@ -161,7 +168,7 @@ QuadTreeNode::QuadTreeNode(World* terrain, ChildDirection dir, float size, const pos = mCenter - pos; mSceneNode->setPosition(Ogre::Vector3(pos.x*8192, pos.y*8192, 0)); - mLodLevel = log2(mSize); + mLodLevel = Log2(mSize); mMaterialGenerator = new MaterialGenerator(mTerrain->getShadersEnabled()); } From e5ce94c33604b51afc2e1ecfdbe4d269e1ba97f5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 Aug 2013 16:45:51 +0200 Subject: [PATCH 24/40] Fix the water being affected by fog on the map --- files/materials/water.shader | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/files/materials/water.shader b/files/materials/water.shader index a6d0a47e6e..87e90a2916 100644 --- a/files/materials/water.shader +++ b/files/materials/water.shader @@ -3,23 +3,28 @@ #define SIMPLE_WATER @shGlobalSettingBool(simple_water) - #if SIMPLE_WATER // --------------------------------------- SIMPLE WATER --------------------------------------------------- +#define FOG @shGlobalSettingBool(fog) + #ifdef SH_VERTEX_SHADER SH_BEGIN_PROGRAM shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) shVertexInput(float2, uv0) shOutput(float2, UV) - shOutput(float, depth) +#if FOG + shOutput(float, depth) +#endif SH_START_PROGRAM { shOutputPosition = shMatrixMult(wvp, shInputPosition); UV = uv0; +#if FOG depth = shOutputPosition.z; +#endif } #else @@ -38,8 +43,10 @@ shOutputColour(0).xyz = shSample(animatedTexture, UV * 15).xyz * float3(1.0, 1.0, 1.0); shOutputColour(0).w = 0.7; +#if FOG float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); +#endif } #endif From 26b3d93293afc4363fa9e715c217bc8e3dbf5ca5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Aug 2013 18:58:23 +0200 Subject: [PATCH 25/40] streamlined filter syntax --- apps/opencs/model/filter/parser.cpp | 88 +++++++++++++++-------------- apps/opencs/model/filter/parser.hpp | 2 +- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index abdc3bab39..d334a7f634 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -174,14 +174,14 @@ CSMFilter::Token CSMFilter::Parser::checkKeywords (const Token& token) { "true", "false", "and", "or", "not", - "text", "value", + "string", "value", 0 }; std::string string = Misc::StringUtils::lowerCase (token.mString); for (int i=0; sKeywords[i]; ++i) - if (sKeywords[i]==string) + if (sKeywords[i]==string || (string.size()==1 && sKeywords[i][0]==string[0])) return Token (static_cast (i+Token::Type_Keyword_True)); return token; @@ -211,7 +211,7 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() case '[': ++mIndex; return Token (Token::Type_OpenSquare); case ']': ++mIndex; return Token (Token::Type_CloseSquare); case ',': ++mIndex; return Token (Token::Type_Comma); - case '?': ++mIndex; return Token (Token::Type_OneShot); + case '!': ++mIndex; return Token (Token::Type_OneShot); } if (c=='"' || c=='_' || std::isalpha (c) || c==':') @@ -224,54 +224,58 @@ CSMFilter::Token CSMFilter::Parser::getNextToken() return Token (Token::Type_None); } -boost::shared_ptr CSMFilter::Parser::parseImp (bool allowEmpty) +boost::shared_ptr CSMFilter::Parser::parseImp (bool allowEmpty, bool ignoreOneShot) { if (Token token = getNextToken()) { - switch (token.mType) - { - case Token::Type_Keyword_True: + if (token==Token (Token::Type_OneShot)) + token = getNextToken(); - return boost::shared_ptr (new BooleanNode (true)); - - case Token::Type_Keyword_False: - - return boost::shared_ptr (new BooleanNode (false)); - - case Token::Type_Keyword_And: - case Token::Type_Keyword_Or: - - return parseNAry (token); - - case Token::Type_Keyword_Not: + if (token) + switch (token.mType) { - boost::shared_ptr node = parseImp(); + case Token::Type_Keyword_True: + + return boost::shared_ptr (new BooleanNode (true)); + + case Token::Type_Keyword_False: + + return boost::shared_ptr (new BooleanNode (false)); + + case Token::Type_Keyword_And: + case Token::Type_Keyword_Or: + + return parseNAry (token); + + case Token::Type_Keyword_Not: + { + boost::shared_ptr node = parseImp(); + + if (mError) + return boost::shared_ptr(); + + return boost::shared_ptr (new NotNode (node)); + } + + case Token::Type_Keyword_Text: + + return parseText(); + + case Token::Type_Keyword_Value: + + return parseValue(); + + case Token::Type_EOS: + + if (!allowEmpty) + error(); - if (mError) return boost::shared_ptr(); - return boost::shared_ptr (new NotNode (node)); - } + default: - case Token::Type_Keyword_Text: - - return parseText(); - - case Token::Type_Keyword_Value: - - return parseValue(); - - case Token::Type_EOS: - - if (!allowEmpty) error(); - - return boost::shared_ptr(); - - default: - - error(); - } + } } return boost::shared_ptr(); @@ -528,7 +532,7 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined) if (!allowPredefined || token==Token (Token::Type_OneShot)) { - boost::shared_ptr node = parseImp (true); + boost::shared_ptr node = parseImp (true, token!=Token (Token::Type_OneShot)); if (mError) return false; diff --git a/apps/opencs/model/filter/parser.hpp b/apps/opencs/model/filter/parser.hpp index fbaf6972e2..5700102cf1 100644 --- a/apps/opencs/model/filter/parser.hpp +++ b/apps/opencs/model/filter/parser.hpp @@ -31,7 +31,7 @@ namespace CSMFilter Token checkKeywords (const Token& token); ///< Turn string token into keyword token, if possible. - boost::shared_ptr parseImp (bool allowEmpty = false); + boost::shared_ptr parseImp (bool allowEmpty = false, bool ignoreOneShot = false); ///< Will return a null-pointer, if there is nothing more to parse. boost::shared_ptr parseNAry (const Token& keyword); From 16331bf1ede22a854a4da06c6c6b8cabd1bd90bd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 13:26:57 -0700 Subject: [PATCH 26/40] Avoid a hack to play the underwater sound properly --- apps/openmw/mwbase/soundmanager.hpp | 4 +++- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index b75f6753d8..4d764597cf 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -39,9 +39,11 @@ namespace MWBase Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */ Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */ Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */ - Play_NoTrack = 1<<2 /* (3D only) Play the sound at the given object's position + Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position * but do not keep it updated (the sound will not move with * the object and will not stop when the object is deleted. */ + + Play_LoopNoEnv = Play_Loop | Play_NoEnv }; enum PlayType { Play_TypeSfx = 1<<3, /* Normal SFX sound */ diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 03e2ce6239..ab8f9b8ec6 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -550,10 +550,8 @@ namespace MWSound { env = Env_Underwater; //play underwater sound - //HACK: this sound is always played underwater, so set volume and pitch higher (it's then lowered) - //Currently not possible to play looping sound with no environment if(!getSoundPlaying(MWWorld::Ptr(), "Underwater")) - playSound("Underwater", 1.11, 1.42 ,Play_TypeSfx, Play_Loop ); + playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv); } else { From 02df8ab84165d510c33876dd0fddc0172034a4c2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 13:48:20 -0700 Subject: [PATCH 27/40] Store the underwater sound to easily stop it --- apps/openmw/mwsound/soundmanagerimp.cpp | 11 ++++++----- apps/openmw/mwsound/soundmanagerimp.hpp | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index ab8f9b8ec6..00a0aa18e9 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -103,6 +103,7 @@ namespace MWSound SoundManager::~SoundManager() { + mUnderwaterSound.reset(); mActiveSounds.clear(); mMusic.reset(); mOutput.reset(); @@ -550,13 +551,13 @@ namespace MWSound { env = Env_Underwater; //play underwater sound - if(!getSoundPlaying(MWWorld::Ptr(), "Underwater")) - playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv); + if(!(mUnderwaterSound && mUnderwaterSound->isPlaying())) + mUnderwaterSound = playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv); } - else + else if(mUnderwaterSound) { - //no need to check if it's playing, stop sound does nothing in that case - stopSound("Underwater"); + mUnderwaterSound->stop(); + mUnderwaterSound.reset(); } mOutput->updateListener( diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 2450ba5c37..f62e62d503 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -44,6 +44,8 @@ namespace MWSound typedef std::map SoundMap; SoundMap mActiveSounds; + MWBase::SoundPtr mUnderwaterSound; + Ogre::Vector3 mListenerPos; Ogre::Vector3 mListenerDir; Ogre::Vector3 mListenerUp; From f216b25be89315b7179912b9e42621cb878e710b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 16:04:19 -0700 Subject: [PATCH 28/40] Slightly randomize time between environment sounds We should use the "Minimum Time Between Environmental Sounds" and "Maximum Time Between Environmental Sounds" INI/fallback settings, but we don't have them. --- apps/openmw/mwsound/soundmanagerimp.cpp | 32 ++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 00a0aa18e9..372be83938 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -4,11 +4,10 @@ #include #include -#include "../mwworld/esmstore.hpp" - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwworld/esmstore.hpp" #include "../mwworld/player.hpp" #include "sound_output.hpp" @@ -475,27 +474,32 @@ namespace MWSound void SoundManager::updateRegionSound(float duration) { - MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); + static float sTimeToNextEnvSound = 0.0f; static int total = 0; static std::string regionName = ""; - static float timePassed = 0.0; + static float sTimePassed = 0.0; + MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::Ptr player = world->getPlayer().getPlayer(); + const ESM::Cell *cell = player.getCell()->mCell; - //If the region has changed - timePassed += duration; - if(!current->mCell->isExterior() || timePassed < 10) + sTimePassed += duration; + if(!cell->isExterior() || sTimePassed < sTimeToNextEnvSound) return; - timePassed = 0; - if(regionName != current->mCell->mRegion) + float a = std::rand() / (double)RAND_MAX; + // NOTE: We should use the "Minimum Time Between Environmental Sounds" and + // "Maximum Time Between Environmental Sounds" fallback settings here. + sTimeToNextEnvSound = 5.0f*a + 15.0f*(1.0f-a); + sTimePassed = 0; + + if(regionName != cell->mRegion) { - regionName = current->mCell->mRegion; + regionName = cell->mRegion; total = 0; } - const ESM::Region *regn = - MWBase::Environment::get().getWorld()->getStore().get().search(regionName); - - if (regn == NULL) + const ESM::Region *regn = world->getStore().get().search(regionName); + if(regn == NULL) return; std::vector::const_iterator soundIter; From 189541aa72e2ab7596f0c536fdedbdb9dabaeb69 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 17:08:23 -0700 Subject: [PATCH 29/40] Apply drowning damage based on the update duration 1 damage every 0.33 seconds is 3 damage a second. Applying it this way avoid having to track another stat. --- apps/openmw/mwmechanics/actors.cpp | 44 +++++++++++-------- .../mwmechanics/mechanicsmanagerimp.cpp | 18 +------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index b8d0a87454..8c310ff226 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -11,10 +11,12 @@ #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/player.hpp" #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/soundmanager.hpp" #include "npcstats.hpp" #include "creaturestats.hpp" @@ -162,33 +164,37 @@ namespace MWMechanics void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration) { - NpcStats &stats = MWWorld::Class::get(ptr).getNpcStats(ptr); - if(MWBase::Environment::get().getWorld()->isSubmerged(ptr) && + MWBase::World *world = MWBase::Environment::get().getWorld(); + NpcStats &stats = ptr.getClass().getNpcStats(ptr); + if(world->isSubmerged(ptr) && stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).mMagnitude == 0) { + float timeLeft = 0.0f; if(stats.getFatigue().getCurrent() == 0) stats.setTimeToStartDrowning(0); - - float timeLeft = stats.getTimeToStartDrowning()-duration; - if(timeLeft < 0.0f) - timeLeft = 0.0f; - - stats.setTimeToStartDrowning(timeLeft); + else + { + timeLeft = stats.getTimeToStartDrowning() - duration; + if(timeLeft < 0.0f) + timeLeft = 0.0f; + stats.setTimeToStartDrowning(timeLeft); + } if(timeLeft == 0.0f) - stats.setLastDrowningHitTime(stats.getLastDrowningHitTime()+duration); + { + // If drowning, apply 3 points of damage per second + ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - 3.0f*duration); + + // Play a drowning sound as necessary for the player + if(ptr == world->getPlayer().getPlayer()) + { + MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); + if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown")) + sndmgr->playSound("drown", 1.0f, 1.0f); + } + } } else - { stats.setTimeToStartDrowning(20); - stats.setLastDrowningHitTime(0); - } - //if npc is drowning and it's time to hit, then hit - while(stats.getTimeToStartDrowning() == 0.0f && stats.getLastDrowningHitTime() > 0.33f) - { - stats.setLastDrowningHitTime(stats.getLastDrowningHitTime()-0.33f); - //fixme: replace it with something different once screen hit effects are implemented (blood on screen) - MWWorld::Class::get(ptr).setActorHealth(ptr, stats.getHealth().getCurrent()-1.0f); - } } Actors::Actors() : mDuration (0) {} diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index c559e4445f..853b2027e5 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -8,7 +8,6 @@ #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/dialoguemanager.hpp" -#include "../mwbase/soundmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" @@ -288,23 +287,10 @@ namespace MWMechanics MWBase::Environment::get().getWindowManager()->setValue ("level", stats.getLevel()); } - //update drowning sound - MWBase::World *world = MWBase::Environment::get().getWorld(); - MWBase::SoundManager * sndmgr = MWBase::Environment::get().getSoundManager(); - MWWorld::Ptr playerPtr = world->getPlayer().getPlayer(); - NpcStats& playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); - if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown") && playerStats.getTimeToStartDrowning()==0.0) - { - sndmgr->playSound("drown",1.0,1.0,MWBase::SoundManager::Play_TypeSfx,MWBase::SoundManager::Play_Loop); - } - if(playerStats.getTimeToStartDrowning()>0.0) - { - //no need to check if it's playing, stop sound does nothing in that case - sndmgr->stopSound("drown"); - } - if (mUpdatePlayer) { + MWBase::World *world = MWBase::Environment::get().getWorld(); + // basic player profile; should not change anymore after the creation phase is finished. MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); From 39af9a13fa8d391e8a83ad35c5b8473aa6df3f0f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 17:13:49 -0700 Subject: [PATCH 30/40] Remove some unused functions --- apps/openmw/mwmechanics/npcstats.cpp | 12 +----------- apps/openmw/mwmechanics/npcstats.hpp | 7 +------ 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 6a5e5a98f4..0b36982890 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -422,7 +422,7 @@ void MWMechanics::NpcStats::modifyProfit(int diff) mProfit += diff; } -float MWMechanics::NpcStats::getTimeToStartDrowning() +float MWMechanics::NpcStats::getTimeToStartDrowning() const { return mTimeToStartDrowning; } @@ -431,13 +431,3 @@ void MWMechanics::NpcStats::setTimeToStartDrowning(float time) assert(time>=0 && time<=20); mTimeToStartDrowning=time; } - -float MWMechanics::NpcStats::getLastDrowningHitTime() -{ - return mLastDrowningHit; -} - -void MWMechanics::NpcStats::setLastDrowningHitTime(float time) -{ - mLastDrowningHit=time; -} diff --git a/apps/openmw/mwmechanics/npcstats.hpp b/apps/openmw/mwmechanics/npcstats.hpp index d3fe61829e..6b7efa5b72 100644 --- a/apps/openmw/mwmechanics/npcstats.hpp +++ b/apps/openmw/mwmechanics/npcstats.hpp @@ -147,15 +147,10 @@ namespace MWMechanics int getWerewolfKills() const; - float getTimeToStartDrowning(); + float getTimeToStartDrowning() const; /// Sets time left for the creature to drown if it stays underwater. /// @param time value from [0,20] void setTimeToStartDrowning(float time); - - float getLastDrowningHitTime(); - /// Sets time since last hit caused by drowning. - /// @param time value from [0,0.33] - void setLastDrowningHitTime(float time); }; } From 33c173a23ab4f1a1869dfe396a40827826fe5244 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 17:22:07 -0700 Subject: [PATCH 31/40] Update the watched Ptr when changing it --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 853b2027e5..238aabbaa8 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -188,6 +188,9 @@ namespace MWMechanics void MechanicsManager::updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) { + if(old == mWatched) + mWatched = ptr; + if(MWWorld::Class::get(ptr).isActor()) mActors.updateActor(old, ptr); else From 281fdbd81bcad454d04552f9dc371303a5925d5a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 17:56:47 -0700 Subject: [PATCH 32/40] Cleanup some redundancy --- .../mwmechanics/mechanicsmanagerimp.cpp | 73 +++++++++---------- .../mwmechanics/mechanicsmanagerimp.hpp | 3 +- 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 238aabbaa8..bd5b8e9e37 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -215,79 +215,74 @@ namespace MWMechanics void MechanicsManager::update(float duration, bool paused) { - if (!mWatched.isEmpty()) + if(!mWatched.isEmpty()) { - MWMechanics::CreatureStats& stats = - MWWorld::Class::get (mWatched).getCreatureStats (mWatched); - - MWMechanics::NpcStats& npcStats = - MWWorld::Class::get (mWatched).getNpcStats (mWatched); - - static const char *attributeNames[8] = + static const char attributeNames[8][12] = { "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", "AttribVal6", "AttribVal7", "AttribVal8" }; - - static const char *dynamicNames[3] = + static const char dynamicNames[3][5] = { "HBar", "MBar", "FBar" }; - for (int i=0; i<8; ++i) + MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); + const MWMechanics::NpcStats &stats = mWatched.getClass().getNpcStats(mWatched); + for(int i = 0;i < ESM::Attribute::Length;++i) { - if (stats.getAttribute(i)!=mWatchedCreature.getAttribute(i)) + if(stats.getAttribute(i) != mWatchedStats.getAttribute(i)) { - mWatchedCreature.setAttribute(i, stats.getAttribute(i)); - - MWBase::Environment::get().getWindowManager()->setValue (attributeNames[i], stats.getAttribute(i)); + mWatchedStats.setAttribute(i, stats.getAttribute(i)); + winMgr->setValue(attributeNames[i], stats.getAttribute(i)); } } - if (stats.getHealth() != mWatchedCreature.getHealth()) { - mWatchedCreature.setHealth(stats.getHealth()); - MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[0], stats.getHealth()); + if(stats.getHealth() != mWatchedStats.getHealth()) + { + mWatchedStats.setHealth(stats.getHealth()); + winMgr->setValue(dynamicNames[0], stats.getHealth()); } - if (stats.getMagicka() != mWatchedCreature.getMagicka()) { - mWatchedCreature.setMagicka(stats.getMagicka()); - MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[1], stats.getMagicka()); + if(stats.getMagicka() != mWatchedStats.getMagicka()) + { + mWatchedStats.setMagicka(stats.getMagicka()); + winMgr->setValue(dynamicNames[1], stats.getMagicka()); } - if (stats.getFatigue() != mWatchedCreature.getFatigue()) { - mWatchedCreature.setFatigue(stats.getFatigue()); - MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[2], stats.getFatigue()); + if(stats.getFatigue() != mWatchedStats.getFatigue()) + { + mWatchedStats.setFatigue(stats.getFatigue()); + winMgr->setValue(dynamicNames[2], stats.getFatigue()); } - if(npcStats.getTimeToStartDrowning() != mWatchedNpc.getTimeToStartDrowning()) + if(stats.getTimeToStartDrowning() != mWatchedStats.getTimeToStartDrowning()) { - mWatchedNpc.setTimeToStartDrowning(npcStats.getTimeToStartDrowning()); - if(npcStats.getTimeToStartDrowning()>=20.0) - { - MWBase::Environment::get().getWindowManager()->setDrowningBarVisibility(false); - } + mWatchedStats.setTimeToStartDrowning(stats.getTimeToStartDrowning()); + if(stats.getTimeToStartDrowning() >= 20.0f) + winMgr->setDrowningBarVisibility(false); else { - MWBase::Environment::get().getWindowManager()->setDrowningBarVisibility(true); - MWBase::Environment::get().getWindowManager()->setDrowningTimeLeft(npcStats.getTimeToStartDrowning()); + winMgr->setDrowningBarVisibility(true); + winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning()); } } bool update = false; //Loop over ESM::Skill::SkillEnum - for(int i = 0; i < 27; ++i) + for(int i = 0; i < ESM::Skill::Length; ++i) { - if(npcStats.getSkill (i) != mWatchedNpc.getSkill (i)) + if(stats.getSkill(i) != mWatchedStats.getSkill(i)) { update = true; - mWatchedNpc.getSkill (i) = npcStats.getSkill (i); - MWBase::Environment::get().getWindowManager()->setValue((ESM::Skill::SkillEnum)i, npcStats.getSkill (i)); + mWatchedStats.getSkill(i) = stats.getSkill(i); + winMgr->setValue((ESM::Skill::SkillEnum)i, stats.getSkill(i)); } } - if (update) - MWBase::Environment::get().getWindowManager()->updateSkillArea(); + if(update) + winMgr->updateSkillArea(); - MWBase::Environment::get().getWindowManager()->setValue ("level", stats.getLevel()); + winMgr->setValue("level", stats.getLevel()); } if (mUpdatePlayer) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 95f760d113..ad07562c7b 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -25,8 +25,7 @@ namespace MWMechanics class MechanicsManager : public MWBase::MechanicsManager { MWWorld::Ptr mWatched; - CreatureStats mWatchedCreature; - NpcStats mWatchedNpc; + NpcStats mWatchedStats; bool mUpdatePlayer; bool mClassSelected; bool mRaceSelected; From 305b5fec0fb26b247daeced91c536c966ff00e53 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 21:40:31 -0700 Subject: [PATCH 33/40] Avoid needlessly copying the MagicEffects --- apps/openmw/mwmechanics/actors.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 8c310ff226..bfe476adb1 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -135,30 +135,27 @@ namespace MWMechanics void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr) { - CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + CreatureStats &creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr); + const MagicEffects &effects = creatureStats.getMagicEffects(); // attributes - for (int i=0; i<8; ++i) + for(int i = 0;i < ESM::Attribute::Length;++i) { - int modifier = - creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyAttribute, i)).mMagnitude; + Stat stat = creatureStats.getAttribute(i); + stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude - + effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude); - modifier -= creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::DrainAttribute, i)).mMagnitude; - - creatureStats.getAttribute(i).setModifier (modifier); + creatureStats.setAttribute(i, stat); } // dynamic stats - MagicEffects effects = creatureStats.getMagicEffects(); - - for (int i=0; i<3; ++i) + for(int i = 0;i < 3;++i) { - DynamicStat stat = creatureStats.getDynamic (i); + DynamicStat stat = creatureStats.getDynamic(i); + stat.setModifier(effects.get(EffectKey(80+i)).mMagnitude - + effects.get(EffectKey(18+i)).mMagnitude); - stat.setModifier ( - effects.get (EffectKey(80+i)).mMagnitude - effects.get (EffectKey(18+i)).mMagnitude); - - creatureStats.setDynamic (i, stat); + creatureStats.setDynamic(i, stat); } } From 92082dae66b73cfad33baed01f158d4fffd767bc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Aug 2013 22:44:52 -0700 Subject: [PATCH 34/40] Modify the current magicka and fatigue when the base changes --- apps/openmw/mwmechanics/actors.cpp | 20 +++++++++++--------- apps/openmw/mwmechanics/stat.hpp | 12 ++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index bfe476adb1..566d4bc505 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -70,22 +70,24 @@ namespace MWMechanics { CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); - int strength = creatureStats.getAttribute(0).getBase(); - int intelligence = creatureStats.getAttribute(1).getBase(); - int willpower = creatureStats.getAttribute(2).getBase(); - int agility = creatureStats.getAttribute(3).getBase(); - int endurance = creatureStats.getAttribute(5).getBase(); + int strength = creatureStats.getAttribute(ESM::Attribute::Strength).getBase(); + int intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getBase(); + int willpower = creatureStats.getAttribute(ESM::Attribute::Willpower).getBase(); + int agility = creatureStats.getAttribute(ESM::Attribute::Agility).getBase(); + int endurance = creatureStats.getAttribute(ESM::Attribute::Endurance).getBase(); double magickaFactor = creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude * 0.1 + 0.5; DynamicStat magicka = creatureStats.getMagicka(); - magicka.setBase (static_cast (intelligence + magickaFactor * intelligence)); - creatureStats.setMagicka (magicka); + float diff = (static_cast(intelligence + magickaFactor*intelligence)) - magicka.getBase(); + magicka.modify(diff); + creatureStats.setMagicka(magicka); DynamicStat fatigue = creatureStats.getFatigue(); - fatigue.setBase (strength+willpower+agility+endurance); - creatureStats.setFatigue (fatigue); + diff = (strength+willpower+agility+endurance) - fatigue.getBase(); + fatigue.modify(diff); + creatureStats.setFatigue(fatigue); } void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration) diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index 606671389a..65d47c9c08 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -42,6 +42,18 @@ namespace MWMechanics mBase = mModified = value; } + void modify(const T& diff) + { + mBase += diff; + if(mBase >= static_cast(0)) + mModified += diff; + else + { + mModified += diff - mBase; + mBase = static_cast(0); + } + } + /// Set base and adjust modified accordingly. void setBase (const T& value) { From 5918b846669f845a9aa9a3b2889b4fcfb872931b Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 Aug 2013 17:04:38 +0200 Subject: [PATCH 35/40] Don't crash on resize events during load --- apps/openmw/mwgui/windowmanagerimp.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index ad1d9a60b5..bf8b664daa 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -929,6 +929,10 @@ namespace MWGui void WindowManager::windowResized(int x, int y) { + mGuiManager->windowResized(); + mLoadingScreen->onResChange (x,y); + if (!mHud) + return; // UI not initialized yet mHud->onResChange(x, y); mConsole->onResChange(x, y); mMenu->onResChange(x, y); @@ -938,10 +942,8 @@ namespace MWGui mBookWindow->center(); mQuickKeysMenu->center(); mSpellBuyingWindow->center(); - mLoadingScreen->onResChange (x,y); mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y)); mInputBlocker->setSize(MyGUI::IntSize(x,y)); - mGuiManager->windowResized(); } void WindowManager::pushGuiMode(GuiMode mode) From 84d259ab8e354148bb2e040a820ea2dc8757b91a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 28 Aug 2013 10:50:29 -0700 Subject: [PATCH 36/40] Avoid reconstructing strings for updating the dynamic stats Attributes still do this, but they change infrequently enough that it doesn't matter. --- .../mwmechanics/mechanicsmanagerimp.cpp | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index bd5b8e9e37..8c13db7900 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -217,41 +217,37 @@ namespace MWMechanics { if(!mWatched.isEmpty()) { - static const char attributeNames[8][12] = - { - "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", - "AttribVal6", "AttribVal7", "AttribVal8" - }; - static const char dynamicNames[3][5] = - { - "HBar", "MBar", "FBar" - }; - MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); const MWMechanics::NpcStats &stats = mWatched.getClass().getNpcStats(mWatched); for(int i = 0;i < ESM::Attribute::Length;++i) { if(stats.getAttribute(i) != mWatchedStats.getAttribute(i)) { + std::stringstream attrname; + attrname << "AttribVal"<<(i+1); + mWatchedStats.setAttribute(i, stats.getAttribute(i)); - winMgr->setValue(attributeNames[i], stats.getAttribute(i)); + winMgr->setValue(attrname.str(), stats.getAttribute(i)); } } if(stats.getHealth() != mWatchedStats.getHealth()) { + static const std::string hbar("HBar"); mWatchedStats.setHealth(stats.getHealth()); - winMgr->setValue(dynamicNames[0], stats.getHealth()); + winMgr->setValue(hbar, stats.getHealth()); } if(stats.getMagicka() != mWatchedStats.getMagicka()) { + static const std::string mbar("MBar"); mWatchedStats.setMagicka(stats.getMagicka()); - winMgr->setValue(dynamicNames[1], stats.getMagicka()); + winMgr->setValue(mbar, stats.getMagicka()); } if(stats.getFatigue() != mWatchedStats.getFatigue()) { + static const std::string fbar("FBar"); mWatchedStats.setFatigue(stats.getFatigue()); - winMgr->setValue(dynamicNames[2], stats.getFatigue()); + winMgr->setValue(fbar, stats.getFatigue()); } if(stats.getTimeToStartDrowning() != mWatchedStats.getTimeToStartDrowning()) From e589d0ec91580010d4ce70c310c839b5ebaf4d13 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 28 Aug 2013 11:36:22 -0700 Subject: [PATCH 37/40] Werewolves can't activate activators --- apps/openmw/mwclass/activator.cpp | 27 +++++++++++++++++++++++++-- apps/openmw/mwclass/activator.hpp | 3 +++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 3a60d9c397..583cb08d39 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -6,19 +6,26 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/world.hpp" #include "../mwworld//cellstore.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/action.hpp" +#include "../mwworld/failedaction.hpp" +#include "../mwworld/nullaction.hpp" #include "../mwrender/actors.hpp" #include "../mwrender/renderinginterface.hpp" #include "../mwgui/tooltips.hpp" +#include "../mwmechanics/npcstats.hpp" + + namespace MWClass { - void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const + void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); if (!model.empty()) { @@ -94,7 +101,23 @@ namespace MWClass return info; } - + + boost::shared_ptr Activator::activate(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const + { + if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf()) + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Sound *sound = store.get().searchRandom("WolfActivator"); + + boost::shared_ptr action(new MWWorld::FailedAction("#{sWerewolfRefusal}")); + if(sound) action->setSound(sound->mId); + + return action; + } + return boost::shared_ptr(new MWWorld::NullAction); + } + + MWWorld::Ptr Activator::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 4165fbc080..1e772ef4f2 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -31,6 +31,9 @@ namespace MWClass virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; + ///< Generate action for activation + static void registerSelf(); virtual std::string getModel(const MWWorld::Ptr &ptr) const; From 9f0b34eae04126fe9ec6cb61fc8abc23980f32ef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Aug 2013 13:27:54 +0200 Subject: [PATCH 38/40] fixed reference loading code (editor) --- apps/opencs/model/world/cell.cpp | 2 +- apps/opencs/model/world/ref.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/opencs/model/world/cell.cpp b/apps/opencs/model/world/cell.cpp index fc367d1cc8..cd58fca1e4 100644 --- a/apps/opencs/model/world/cell.cpp +++ b/apps/opencs/model/world/cell.cpp @@ -7,7 +7,7 @@ void CSMWorld::Cell::load (ESM::ESMReader &esm) { mName = mId; - ESM::Cell::load (esm, true); /// \todo set this to false, once the bug in ESM::Cell::load is fixed + ESM::Cell::load (esm, false); if (!(mData.mFlags & Interior)) { diff --git a/apps/opencs/model/world/ref.cpp b/apps/opencs/model/world/ref.cpp index e5e948928e..af363bafb4 100644 --- a/apps/opencs/model/world/ref.cpp +++ b/apps/opencs/model/world/ref.cpp @@ -8,8 +8,6 @@ void CSMWorld::CellRef::load (ESM::ESMReader &esm, Cell& cell, const std::string mId = id; mCellId = cell.mId; - cell.getNextRef (esm, *this); - if (!mDeleted) cell.addRef (mId); } \ No newline at end of file From c8e31725dcd56c6d60c1946c0b554e6140a42398 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 Aug 2013 15:15:40 +0200 Subject: [PATCH 39/40] Fix weather sounds persisting on a new game --- apps/openmw/mwworld/weather.cpp | 5 +++++ apps/openmw/mwworld/weather.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 587b7847bc..6f5dbe23fe 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -167,6 +167,11 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa setFallbackWeather(blizzard,"blizzard"); } +WeatherManager::~WeatherManager() +{ + stopSounds(true); +} + void WeatherManager::setWeather(const String& weather, bool instant) { if (weather == mCurrentWeather && mNextWeather == "") diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index a2a07cec79..80cbe0418e 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -120,6 +120,7 @@ namespace MWWorld { public: WeatherManager(MWRender::RenderingManager*,MWWorld::Fallback* fallback); + ~WeatherManager(); /** * Change the weather in the specified region From f4e9199f784b434f9833e6e1d0ed291a227f2bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20S=C3=B6derberg?= Date: Thu, 29 Aug 2013 16:21:11 +0200 Subject: [PATCH 40/40] Various chargen tweaks --- files/mygui/openmw_chargen_birth.layout | 8 +-- files/mygui/openmw_chargen_class.layout | 10 +++- .../openmw_chargen_class_description.layout | 2 +- .../mygui/openmw_chargen_create_class.layout | 14 ++++-- files/mygui/openmw_chargen_review.layout | 50 +++++++++---------- 5 files changed, 49 insertions(+), 35 deletions(-) diff --git a/files/mygui/openmw_chargen_birth.layout b/files/mygui/openmw_chargen_birth.layout index e8d959ba22..b368a6407c 100644 --- a/files/mygui/openmw_chargen_birth.layout +++ b/files/mygui/openmw_chargen_birth.layout @@ -1,11 +1,12 @@ - + + - + @@ -13,7 +14,7 @@ - + @@ -24,5 +25,6 @@ + diff --git a/files/mygui/openmw_chargen_class.layout b/files/mygui/openmw_chargen_class.layout index aac97870c7..3c0348b663 100644 --- a/files/mygui/openmw_chargen_class.layout +++ b/files/mygui/openmw_chargen_class.layout @@ -1,7 +1,8 @@ - + + @@ -20,6 +21,7 @@ + @@ -32,6 +34,7 @@ + @@ -40,6 +43,7 @@ + @@ -51,6 +55,7 @@ + @@ -60,7 +65,7 @@ - + @@ -71,5 +76,6 @@ + diff --git a/files/mygui/openmw_chargen_class_description.layout b/files/mygui/openmw_chargen_class_description.layout index e003f22c19..eaf754697d 100644 --- a/files/mygui/openmw_chargen_class_description.layout +++ b/files/mygui/openmw_chargen_class_description.layout @@ -17,6 +17,6 @@ - + diff --git a/files/mygui/openmw_chargen_create_class.layout b/files/mygui/openmw_chargen_create_class.layout index e9c4146a0b..92382640b9 100644 --- a/files/mygui/openmw_chargen_create_class.layout +++ b/files/mygui/openmw_chargen_create_class.layout @@ -1,13 +1,15 @@ - + - + + + @@ -19,6 +21,7 @@ + @@ -31,6 +34,7 @@ + @@ -39,6 +43,7 @@ + @@ -50,6 +55,7 @@ + @@ -59,7 +65,7 @@ - + @@ -73,6 +79,6 @@ - + diff --git a/files/mygui/openmw_chargen_review.layout b/files/mygui/openmw_chargen_review.layout index 408d4f471e..5d18f4bff8 100644 --- a/files/mygui/openmw_chargen_review.layout +++ b/files/mygui/openmw_chargen_review.layout @@ -1,9 +1,9 @@ - + - + @@ -17,27 +17,27 @@ - - - - + + + + - - - + + + - + - + @@ -46,57 +46,57 @@ - - + + - + - + - + - + - + - + - + @@ -105,13 +105,13 @@ - - - + + + - - + +