From: Mikko Rasa Date: Tue, 10 Jul 2007 19:20:20 +0000 (+0000) Subject: Initial revision X-Git-Url: http://git.tdb.fi/?p=r2c2.git;a=commitdiff_plain;h=6c61179fe09af2f5366d50f10aadbf5f83438087 Initial revision --- diff --git a/Build b/Build new file mode 100644 index 0000000..df11fe0 --- /dev/null +++ b/Build @@ -0,0 +1,67 @@ +package "märklin" +{ + require "mspcore"; + require "sigc++-2.0"; + + program "shoppinglist" + { + source "source/shoppinglist"; + require "mspparser"; + }; + + library "marklin" + { + source "source/libmarklin"; + require "mspparser"; + }; + + library "marklin3d" + { + source "source/3d"; + require "mspgl"; + build_info + { + incpath "source"; + library "marklin"; + libpath "."; + }; + }; + + /*program "newconsole" + { + source "source/newconsole"; + build_info + { + library "marklincontrol"; + incpath "source"; + libpath "."; + }; + };*/ + + program "designer" + { + source "source/designer"; + require "mspstrings"; + require "sdl"; + build_info + { + incpath "source"; + library "marklin3d"; + libpath "."; + }; + }; + + program "engineer" + { + source "source/engineer"; + require "mspstrings"; + require "mspgltk"; + require "sdl"; + build_info + { + incpath "source"; + library "marklin3d"; + libpath "."; + }; + }; +}; diff --git a/dejavu-12.font b/dejavu-12.font new file mode 100644 index 0000000..8d7e902 --- /dev/null +++ b/dejavu-12.font @@ -0,0 +1,1341 @@ +texture "dejavu-12.png"; +default_size 12; +ascent 1.167; +descent 0.083; +glyph 32 +{ + texcoords 0.035156 0.945312 0.035156 0.945312; + size 0.000 0.000; + offset 0.000 0.000; + advance 0.333; +}; +glyph 33 +{ + texcoords 0.101562 0.945312 0.105469 0.980469; + size 0.083 0.750; + offset 0.167 0.000; + advance 0.417; +}; +glyph 34 +{ + texcoords 0.167969 0.968750 0.179688 0.980469; + size 0.250 0.250; + offset 0.083 0.500; + advance 0.417; +}; +glyph 35 +{ + texcoords 0.230469 0.945312 0.261719 0.976562; + size 0.667 0.667; + offset 0.083 0.000; + advance 0.833; +}; +glyph 36 +{ + texcoords 0.304688 0.937500 0.328125 0.980469; + size 0.500 0.917; + offset 0.167 -0.167; + advance 0.667; +}; +glyph 37 +{ + texcoords 0.367188 0.945312 0.406250 0.980469; + size 0.833 0.750; + offset 0.000 0.000; + advance 0.917; +}; +glyph 38 +{ + texcoords 0.437500 0.945312 0.472656 0.980469; + size 0.750 0.750; + offset 0.083 0.000; + advance 0.833; +}; +glyph 39 +{ + texcoords 0.523438 0.968750 0.527344 0.980469; + size 0.083 0.250; + offset 0.083 0.500; + advance 0.250; +}; +glyph 40 +{ + texcoords 0.589844 0.941406 0.601562 0.984375; + size 0.250 0.917; + offset 0.083 -0.083; + advance 0.417; +}; +glyph 41 +{ + texcoords 0.660156 0.941406 0.671875 0.984375; + size 0.250 0.917; + offset 0.083 -0.083; + advance 0.417; +}; +glyph 42 +{ + texcoords 0.726562 0.957031 0.746094 0.980469; + size 0.417 0.500; + offset 0.083 0.250; + advance 0.500; +}; +glyph 43 +{ + texcoords 0.792969 0.945312 0.820312 0.972656; + size 0.583 0.583; + offset 0.083 0.000; + advance 0.833; +}; +glyph 44 +{ + texcoords 0.875000 0.941406 0.878906 0.953125; + size 0.083 0.250; + offset 0.083 -0.083; + advance 0.333; +}; +glyph 45 +{ + texcoords 0.941406 0.957031 0.953125 0.960938; + size 0.250 0.083; + offset 0.083 0.250; + advance 0.333; +}; +glyph 46 +{ + texcoords 0.031250 0.875000 0.035156 0.882812; + size 0.083 0.167; + offset 0.083 0.000; + advance 0.333; +}; +glyph 47 +{ + texcoords 0.097656 0.871094 0.113281 0.910156; + size 0.333 0.833; + offset 0.000 -0.083; + advance 0.333; +}; +glyph 48 +{ + texcoords 0.164062 0.875000 0.187500 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 49 +{ + texcoords 0.234375 0.875000 0.253906 0.910156; + size 0.417 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 50 +{ + texcoords 0.300781 0.875000 0.328125 0.910156; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 51 +{ + texcoords 0.375000 0.875000 0.398438 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 52 +{ + texcoords 0.445312 0.875000 0.468750 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 53 +{ + texcoords 0.515625 0.875000 0.539062 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 54 +{ + texcoords 0.585938 0.875000 0.609375 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 55 +{ + texcoords 0.656250 0.875000 0.679688 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 56 +{ + texcoords 0.726562 0.875000 0.750000 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 57 +{ + texcoords 0.796875 0.875000 0.820312 0.910156; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 58 +{ + texcoords 0.875000 0.875000 0.878906 0.898438; + size 0.083 0.500; + offset 0.083 0.000; + advance 0.333; +}; +glyph 59 +{ + texcoords 0.945312 0.871094 0.949219 0.898438; + size 0.083 0.583; + offset 0.083 -0.083; + advance 0.333; +}; +glyph 60 +{ + texcoords 0.019531 0.808594 0.050781 0.832031; + size 0.667 0.500; + offset 0.083 0.083; + advance 0.833; +}; +glyph 61 +{ + texcoords 0.089844 0.812500 0.121094 0.824219; + size 0.667 0.250; + offset 0.083 0.167; + advance 0.833; +}; +glyph 62 +{ + texcoords 0.160156 0.808594 0.191406 0.832031; + size 0.667 0.500; + offset 0.083 0.083; + advance 0.833; +}; +glyph 63 +{ + texcoords 0.234375 0.804688 0.253906 0.839844; + size 0.417 0.750; + offset 0.000 0.000; + advance 0.500; +}; +glyph 64 +{ + texcoords 0.292969 0.796875 0.335938 0.839844; + size 0.917 0.917; + offset 0.083 -0.167; + advance 1.083; +}; +glyph 65 +{ + texcoords 0.371094 0.804688 0.402344 0.839844; + size 0.667 0.750; + offset 0.000 0.000; + advance 0.667; +}; +glyph 66 +{ + texcoords 0.445312 0.804688 0.468750 0.839844; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 67 +{ + texcoords 0.515625 0.804688 0.539062 0.839844; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 68 +{ + texcoords 0.582031 0.804688 0.609375 0.839844; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 69 +{ + texcoords 0.656250 0.804688 0.679688 0.839844; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 70 +{ + texcoords 0.726562 0.804688 0.746094 0.839844; + size 0.417 0.750; + offset 0.083 0.000; + advance 0.583; +}; +glyph 71 +{ + texcoords 0.792969 0.804688 0.820312 0.839844; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 72 +{ + texcoords 0.863281 0.804688 0.890625 0.839844; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 73 +{ + texcoords 0.945312 0.804688 0.949219 0.839844; + size 0.083 0.750; + offset 0.083 0.000; + advance 0.250; +}; +glyph 74 +{ + texcoords 0.027344 0.726562 0.039062 0.769531; + size 0.250 0.917; + offset -0.083 -0.167; + advance 0.250; +}; +glyph 75 +{ + texcoords 0.089844 0.734375 0.117188 0.769531; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.583; +}; +glyph 76 +{ + texcoords 0.164062 0.734375 0.183594 0.769531; + size 0.417 0.750; + offset 0.083 0.000; + advance 0.500; +}; +glyph 77 +{ + texcoords 0.230469 0.734375 0.261719 0.769531; + size 0.667 0.750; + offset 0.083 0.000; + advance 0.833; +}; +glyph 78 +{ + texcoords 0.300781 0.734375 0.328125 0.769531; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 79 +{ + texcoords 0.371094 0.734375 0.398438 0.769531; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 80 +{ + texcoords 0.445312 0.734375 0.468750 0.769531; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 81 +{ + texcoords 0.511719 0.726562 0.539062 0.769531; + size 0.583 0.917; + offset 0.083 -0.167; + advance 0.750; +}; +glyph 82 +{ + texcoords 0.582031 0.734375 0.609375 0.769531; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 83 +{ + texcoords 0.656250 0.734375 0.679688 0.769531; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 84 +{ + texcoords 0.722656 0.734375 0.750000 0.769531; + size 0.583 0.750; + offset 0.000 0.000; + advance 0.583; +}; +glyph 85 +{ + texcoords 0.792969 0.734375 0.820312 0.769531; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 86 +{ + texcoords 0.859375 0.734375 0.898438 0.769531; + size 0.833 0.750; + offset -0.083 0.000; + advance 0.667; +}; +glyph 87 +{ + texcoords 0.925781 0.734375 0.968750 0.769531; + size 0.917 0.750; + offset 0.000 0.000; + advance 0.917; +}; +glyph 88 +{ + texcoords 0.019531 0.664062 0.046875 0.699219; + size 0.583 0.750; + offset 0.000 0.000; + advance 0.583; +}; +glyph 89 +{ + texcoords 0.089844 0.664062 0.117188 0.699219; + size 0.583 0.750; + offset 0.000 0.000; + advance 0.583; +}; +glyph 90 +{ + texcoords 0.160156 0.664062 0.187500 0.699219; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 91 +{ + texcoords 0.242188 0.656250 0.250000 0.699219; + size 0.167 0.917; + offset 0.167 -0.167; + advance 0.417; +}; +glyph 92 +{ + texcoords 0.308594 0.660156 0.324219 0.699219; + size 0.333 0.833; + offset 0.000 -0.083; + advance 0.333; +}; +glyph 93 +{ + texcoords 0.382812 0.656250 0.390625 0.699219; + size 0.167 0.917; + offset 0.083 -0.167; + advance 0.417; +}; +glyph 94 +{ + texcoords 0.441406 0.687500 0.472656 0.699219; + size 0.667 0.250; + offset 0.083 0.500; + advance 0.833; +}; +glyph 95 +{ + texcoords 0.515625 0.652344 0.539062 0.656250; + size 0.500 0.083; + offset 0.000 -0.250; + advance 0.500; +}; +glyph 96 +{ + texcoords 0.589844 0.695312 0.601562 0.703125; + size 0.250 0.167; + offset 0.083 0.667; + advance 0.500; +}; +glyph 97 +{ + texcoords 0.656250 0.664062 0.679688 0.691406; + size 0.500 0.583; + offset 0.083 0.000; + advance 0.667; +}; +glyph 98 +{ + texcoords 0.726562 0.664062 0.750000 0.703125; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 99 +{ + texcoords 0.796875 0.664062 0.816406 0.691406; + size 0.417 0.583; + offset 0.083 0.000; + advance 0.583; +}; +glyph 100 +{ + texcoords 0.867188 0.664062 0.890625 0.703125; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 101 +{ + texcoords 0.937500 0.664062 0.960938 0.691406; + size 0.500 0.583; + offset 0.083 0.000; + advance 0.667; +}; +glyph 102 +{ + texcoords 0.027344 0.593750 0.042969 0.632812; + size 0.333 0.833; + offset 0.000 0.000; + advance 0.333; +}; +glyph 103 +{ + texcoords 0.093750 0.582031 0.117188 0.621094; + size 0.500 0.833; + offset 0.083 -0.250; + advance 0.667; +}; +glyph 104 +{ + texcoords 0.164062 0.593750 0.187500 0.632812; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 105 +{ + texcoords 0.242188 0.593750 0.246094 0.628906; + size 0.083 0.750; + offset 0.083 0.000; + advance 0.250; +}; +glyph 106 +{ + texcoords 0.312500 0.582031 0.320312 0.628906; + size 0.167 1.000; + offset 0.000 -0.250; + advance 0.250; +}; +glyph 107 +{ + texcoords 0.375000 0.593750 0.398438 0.632812; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.583; +}; +glyph 108 +{ + texcoords 0.453125 0.593750 0.457031 0.632812; + size 0.083 0.833; + offset 0.083 0.000; + advance 0.250; +}; +glyph 109 +{ + texcoords 0.507812 0.593750 0.542969 0.621094; + size 0.750 0.583; + offset 0.083 0.000; + advance 0.917; +}; +glyph 110 +{ + texcoords 0.585938 0.593750 0.609375 0.621094; + size 0.500 0.583; + offset 0.083 0.000; + advance 0.667; +}; +glyph 111 +{ + texcoords 0.656250 0.593750 0.679688 0.621094; + size 0.500 0.583; + offset 0.083 0.000; + advance 0.667; +}; +glyph 112 +{ + texcoords 0.726562 0.582031 0.750000 0.621094; + size 0.500 0.833; + offset 0.083 -0.250; + advance 0.667; +}; +glyph 113 +{ + texcoords 0.796875 0.582031 0.820312 0.621094; + size 0.500 0.833; + offset 0.083 -0.250; + advance 0.667; +}; +glyph 114 +{ + texcoords 0.871094 0.593750 0.886719 0.621094; + size 0.333 0.583; + offset 0.083 0.000; + advance 0.417; +}; +glyph 115 +{ + texcoords 0.937500 0.593750 0.960938 0.621094; + size 0.500 0.583; + offset 0.083 0.000; + advance 0.583; +}; +glyph 116 +{ + texcoords 0.027344 0.523438 0.042969 0.558594; + size 0.333 0.750; + offset 0.000 0.000; + advance 0.417; +}; +glyph 117 +{ + texcoords 0.093750 0.523438 0.117188 0.550781; + size 0.500 0.583; + offset 0.083 0.000; + advance 0.667; +}; +glyph 118 +{ + texcoords 0.160156 0.523438 0.191406 0.550781; + size 0.667 0.583; + offset -0.083 0.000; + advance 0.500; +}; +glyph 119 +{ + texcoords 0.226562 0.523438 0.261719 0.550781; + size 0.750 0.583; + offset 0.000 0.000; + advance 0.750; +}; +glyph 120 +{ + texcoords 0.304688 0.523438 0.328125 0.550781; + size 0.500 0.583; + offset 0.000 0.000; + advance 0.500; +}; +glyph 121 +{ + texcoords 0.371094 0.511719 0.402344 0.550781; + size 0.667 0.833; + offset -0.083 -0.250; + advance 0.500; +}; +glyph 122 +{ + texcoords 0.445312 0.523438 0.464844 0.550781; + size 0.417 0.583; + offset 0.000 0.000; + advance 0.417; +}; +glyph 123 +{ + texcoords 0.515625 0.515625 0.535156 0.558594; + size 0.417 0.917; + offset 0.167 -0.167; + advance 0.667; +}; +glyph 124 +{ + texcoords 0.593750 0.511719 0.597656 0.558594; + size 0.083 1.000; + offset 0.167 -0.250; + advance 0.333; +}; +glyph 125 +{ + texcoords 0.656250 0.515625 0.675781 0.558594; + size 0.417 0.917; + offset 0.083 -0.167; + advance 0.667; +}; +glyph 126 +{ + texcoords 0.722656 0.535156 0.753906 0.546875; + size 0.667 0.250; + offset 0.083 0.250; + advance 0.833; +}; +glyph 160 +{ + texcoords 0.808594 0.523438 0.808594 0.523438; + size 0.000 0.000; + offset 0.000 0.000; + advance 0.333; +}; +glyph 161 +{ + texcoords 0.875000 0.523438 0.878906 0.558594; + size 0.083 0.750; + offset 0.167 0.000; + advance 0.417; +}; +glyph 162 +{ + texcoords 0.937500 0.515625 0.957031 0.558594; + size 0.417 0.917; + offset 0.083 -0.167; + advance 0.667; +}; +glyph 163 +{ + texcoords 0.023438 0.453125 0.042969 0.488281; + size 0.417 0.750; + offset 0.167 0.000; + advance 0.750; +}; +glyph 164 +{ + texcoords 0.089844 0.453125 0.117188 0.484375; + size 0.583 0.667; + offset 0.000 0.000; + advance 0.667; +}; +glyph 165 +{ + texcoords 0.160156 0.453125 0.187500 0.488281; + size 0.583 0.750; + offset 0.083 0.000; + advance 0.750; +}; +glyph 166 +{ + texcoords 0.242188 0.445312 0.246094 0.484375; + size 0.083 0.833; + offset 0.167 -0.167; + advance 0.333; +}; +glyph 167 +{ + texcoords 0.304688 0.449219 0.324219 0.488281; + size 0.417 0.833; + offset 0.000 -0.083; + advance 0.417; +}; +glyph 168 +{ + texcoords 0.378906 0.484375 0.390625 0.488281; + size 0.250 0.083; + offset 0.167 0.667; + advance 0.583; +}; +glyph 169 +{ + texcoords 0.437500 0.453125 0.472656 0.488281; + size 0.750 0.750; + offset 0.167 0.000; + advance 1.000; +}; +glyph 170 +{ + texcoords 0.515625 0.460938 0.539062 0.488281; + size 0.500 0.583; + offset 0.083 0.167; + advance 0.500; +}; +glyph 171 +{ + texcoords 0.585938 0.457031 0.609375 0.476562; + size 0.500 0.417; + offset 0.083 0.083; + advance 0.583; +}; +glyph 172 +{ + texcoords 0.652344 0.460938 0.683594 0.472656; + size 0.667 0.250; + offset 0.083 0.167; + advance 0.833; +}; +glyph 173 +{ + texcoords 0.730469 0.464844 0.742188 0.468750; + size 0.250 0.083; + offset 0.083 0.250; + advance 0.333; +}; +glyph 174 +{ + texcoords 0.789062 0.453125 0.824219 0.488281; + size 0.750 0.750; + offset 0.167 0.000; + advance 1.000; +}; +glyph 175 +{ + texcoords 0.871094 0.484375 0.886719 0.488281; + size 0.333 0.083; + offset 0.083 0.667; + advance 0.500; +}; +glyph 176 +{ + texcoords 0.941406 0.472656 0.957031 0.488281; + size 0.333 0.333; + offset 0.083 0.417; + advance 0.500; +}; +glyph 177 +{ + texcoords 0.019531 0.382812 0.046875 0.410156; + size 0.583 0.583; + offset 0.167 0.000; + advance 0.833; +}; +glyph 178 +{ + texcoords 0.097656 0.398438 0.109375 0.417969; + size 0.250 0.417; + offset 0.083 0.333; + advance 0.417; +}; +glyph 179 +{ + texcoords 0.167969 0.398438 0.183594 0.417969; + size 0.333 0.417; + offset 0.083 0.333; + advance 0.417; +}; +glyph 180 +{ + texcoords 0.238281 0.414062 0.250000 0.421875; + size 0.250 0.167; + offset 0.167 0.667; + advance 0.500; +}; +glyph 181 +{ + texcoords 0.300781 0.371094 0.328125 0.410156; + size 0.583 0.833; + offset 0.083 -0.250; + advance 0.667; +}; +glyph 182 +{ + texcoords 0.375000 0.378906 0.394531 0.417969; + size 0.417 0.833; + offset 0.083 -0.083; + advance 0.667; +}; +glyph 183 +{ + texcoords 0.453125 0.394531 0.457031 0.402344; + size 0.083 0.167; + offset 0.083 0.250; + advance 0.333; +}; +glyph 184 +{ + texcoords 0.523438 0.375000 0.531250 0.382812; + size 0.167 0.167; + offset 0.167 -0.167; + advance 0.500; +}; +glyph 185 +{ + texcoords 0.589844 0.398438 0.601562 0.417969; + size 0.250 0.417; + offset 0.083 0.333; + advance 0.417; +}; +glyph 186 +{ + texcoords 0.656250 0.390625 0.675781 0.417969; + size 0.417 0.583; + offset 0.083 0.167; + advance 0.500; +}; +glyph 187 +{ + texcoords 0.726562 0.386719 0.750000 0.406250; + size 0.500 0.417; + offset 0.083 0.083; + advance 0.583; +}; +glyph 188 +{ + texcoords 0.785156 0.382812 0.828125 0.417969; + size 0.917 0.750; + offset 0.083 0.000; + advance 1.000; +}; +glyph 189 +{ + texcoords 0.859375 0.382812 0.898438 0.417969; + size 0.833 0.750; + offset 0.083 0.000; + advance 1.000; +}; +glyph 190 +{ + texcoords 0.925781 0.382812 0.968750 0.417969; + size 0.917 0.750; + offset 0.083 0.000; + advance 1.000; +}; +glyph 191 +{ + texcoords 0.023438 0.312500 0.042969 0.347656; + size 0.417 0.750; + offset 0.083 0.000; + advance 0.500; +}; +glyph 192 +{ + texcoords 0.089844 0.312500 0.121094 0.359375; + size 0.667 1.000; + offset 0.000 0.000; + advance 0.667; +}; +glyph 193 +{ + texcoords 0.160156 0.312500 0.191406 0.359375; + size 0.667 1.000; + offset 0.000 0.000; + advance 0.667; +}; +glyph 194 +{ + texcoords 0.230469 0.312500 0.261719 0.359375; + size 0.667 1.000; + offset 0.000 0.000; + advance 0.667; +}; +glyph 195 +{ + texcoords 0.300781 0.312500 0.332031 0.359375; + size 0.667 1.000; + offset 0.000 0.000; + advance 0.667; +}; +glyph 196 +{ + texcoords 0.371094 0.312500 0.402344 0.355469; + size 0.667 0.917; + offset 0.000 0.000; + advance 0.667; +}; +glyph 197 +{ + texcoords 0.441406 0.312500 0.472656 0.359375; + size 0.667 1.000; + offset 0.000 0.000; + advance 0.667; +}; +glyph 198 +{ + texcoords 0.503906 0.312500 0.546875 0.347656; + size 0.917 0.750; + offset 0.000 0.000; + advance 1.000; +}; +glyph 199 +{ + texcoords 0.585938 0.304688 0.609375 0.347656; + size 0.500 0.917; + offset 0.083 -0.167; + advance 0.667; +}; +glyph 200 +{ + texcoords 0.656250 0.312500 0.679688 0.359375; + size 0.500 1.000; + offset 0.083 0.000; + advance 0.667; +}; +glyph 201 +{ + texcoords 0.726562 0.312500 0.750000 0.359375; + size 0.500 1.000; + offset 0.083 0.000; + advance 0.667; +}; +glyph 202 +{ + texcoords 0.796875 0.312500 0.820312 0.359375; + size 0.500 1.000; + offset 0.083 0.000; + advance 0.667; +}; +glyph 203 +{ + texcoords 0.867188 0.312500 0.890625 0.355469; + size 0.500 0.917; + offset 0.083 0.000; + advance 0.667; +}; +glyph 204 +{ + texcoords 0.941406 0.312500 0.953125 0.359375; + size 0.250 1.000; + offset 0.083 0.000; + advance 0.250; +}; +glyph 205 +{ + texcoords 0.027344 0.242188 0.039062 0.289062; + size 0.250 1.000; + offset 0.083 0.000; + advance 0.250; +}; +glyph 206 +{ + texcoords 0.093750 0.242188 0.113281 0.289062; + size 0.417 1.000; + offset -0.083 0.000; + advance 0.250; +}; +glyph 207 +{ + texcoords 0.167969 0.242188 0.179688 0.285156; + size 0.250 0.917; + offset 0.000 0.000; + advance 0.250; +}; +glyph 208 +{ + texcoords 0.230469 0.242188 0.261719 0.277344; + size 0.667 0.750; + offset 0.000 0.000; + advance 0.750; +}; +glyph 209 +{ + texcoords 0.300781 0.242188 0.328125 0.289062; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 210 +{ + texcoords 0.371094 0.242188 0.398438 0.289062; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 211 +{ + texcoords 0.441406 0.242188 0.468750 0.289062; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 212 +{ + texcoords 0.511719 0.242188 0.539062 0.289062; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 213 +{ + texcoords 0.582031 0.242188 0.609375 0.289062; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 214 +{ + texcoords 0.652344 0.242188 0.679688 0.285156; + size 0.583 0.917; + offset 0.083 0.000; + advance 0.750; +}; +glyph 215 +{ + texcoords 0.722656 0.242188 0.750000 0.269531; + size 0.583 0.583; + offset 0.167 0.000; + advance 0.833; +}; +glyph 216 +{ + texcoords 0.789062 0.238281 0.824219 0.281250; + size 0.750 0.917; + offset 0.000 -0.083; + advance 0.750; +}; +glyph 217 +{ + texcoords 0.863281 0.242188 0.890625 0.289062; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 218 +{ + texcoords 0.933594 0.242188 0.960938 0.289062; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 219 +{ + texcoords 0.019531 0.171875 0.046875 0.218750; + size 0.583 1.000; + offset 0.083 0.000; + advance 0.750; +}; +glyph 220 +{ + texcoords 0.089844 0.171875 0.117188 0.214844; + size 0.583 0.917; + offset 0.083 0.000; + advance 0.750; +}; +glyph 221 +{ + texcoords 0.160156 0.171875 0.187500 0.218750; + size 0.583 1.000; + offset 0.000 0.000; + advance 0.583; +}; +glyph 222 +{ + texcoords 0.234375 0.171875 0.257812 0.207031; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 223 +{ + texcoords 0.304688 0.171875 0.328125 0.210938; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 224 +{ + texcoords 0.375000 0.171875 0.398438 0.210938; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 225 +{ + texcoords 0.445312 0.171875 0.468750 0.210938; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 226 +{ + texcoords 0.515625 0.171875 0.539062 0.210938; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 227 +{ + texcoords 0.585938 0.171875 0.609375 0.210938; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 228 +{ + texcoords 0.656250 0.171875 0.679688 0.207031; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 229 +{ + texcoords 0.726562 0.171875 0.750000 0.218750; + size 0.500 1.000; + offset 0.083 0.000; + advance 0.667; +}; +glyph 230 +{ + texcoords 0.789062 0.171875 0.828125 0.199219; + size 0.833 0.583; + offset 0.083 0.000; + advance 1.000; +}; +glyph 231 +{ + texcoords 0.867188 0.164062 0.886719 0.199219; + size 0.417 0.750; + offset 0.083 -0.167; + advance 0.583; +}; +glyph 232 +{ + texcoords 0.937500 0.171875 0.960938 0.210938; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 233 +{ + texcoords 0.023438 0.101562 0.046875 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 234 +{ + texcoords 0.093750 0.101562 0.117188 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 235 +{ + texcoords 0.164062 0.101562 0.187500 0.136719; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 236 +{ + texcoords 0.238281 0.101562 0.250000 0.140625; + size 0.250 0.833; + offset 0.000 0.000; + advance 0.250; +}; +glyph 237 +{ + texcoords 0.308594 0.101562 0.320312 0.140625; + size 0.250 0.833; + offset 0.083 0.000; + advance 0.250; +}; +glyph 238 +{ + texcoords 0.375000 0.101562 0.394531 0.140625; + size 0.417 0.833; + offset -0.083 0.000; + advance 0.250; +}; +glyph 239 +{ + texcoords 0.449219 0.101562 0.460938 0.136719; + size 0.250 0.750; + offset 0.000 0.000; + advance 0.250; +}; +glyph 240 +{ + texcoords 0.515625 0.101562 0.539062 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 241 +{ + texcoords 0.585938 0.101562 0.609375 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 242 +{ + texcoords 0.656250 0.101562 0.679688 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 243 +{ + texcoords 0.726562 0.101562 0.750000 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 244 +{ + texcoords 0.796875 0.101562 0.820312 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 245 +{ + texcoords 0.867188 0.101562 0.890625 0.140625; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 246 +{ + texcoords 0.937500 0.101562 0.960938 0.136719; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 247 +{ + texcoords 0.019531 0.035156 0.046875 0.054688; + size 0.583 0.417; + offset 0.083 0.083; + advance 0.833; +}; +glyph 248 +{ + texcoords 0.089844 0.027344 0.121094 0.062500; + size 0.667 0.750; + offset 0.000 -0.083; + advance 0.667; +}; +glyph 249 +{ + texcoords 0.164062 0.031250 0.187500 0.070312; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 250 +{ + texcoords 0.234375 0.031250 0.257812 0.070312; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 251 +{ + texcoords 0.304688 0.031250 0.328125 0.070312; + size 0.500 0.833; + offset 0.083 0.000; + advance 0.667; +}; +glyph 252 +{ + texcoords 0.375000 0.031250 0.398438 0.066406; + size 0.500 0.750; + offset 0.083 0.000; + advance 0.667; +}; +glyph 253 +{ + texcoords 0.441406 0.019531 0.472656 0.070312; + size 0.667 1.083; + offset -0.083 -0.250; + advance 0.500; +}; +glyph 254 +{ + texcoords 0.515625 0.019531 0.539062 0.070312; + size 0.500 1.083; + offset 0.083 -0.250; + advance 0.667; +}; +glyph 255 +{ + texcoords 0.582031 0.019531 0.613281 0.066406; + size 0.667 1.000; + offset -0.083 -0.250; + advance 0.500; +}; diff --git a/dejavu-12.png b/dejavu-12.png new file mode 100644 index 0000000..66fc386 Binary files /dev/null and b/dejavu-12.png differ diff --git a/dejavu-20.font b/dejavu-20.font new file mode 100644 index 0000000..17170ce --- /dev/null +++ b/dejavu-20.font @@ -0,0 +1,1339 @@ +texture "dejavu-20.png"; +default_size 20.000000; +glyph 32 +{ + texcoords 0.023438 0.906250 0.023438 0.906250; + size 0.000000 0.000000; + offset 0.000000 0.000000; + advance 0.300000; +}; +glyph 33 +{ + texcoords 0.070312 0.906250 0.074219 0.964844; + size 0.100000 0.750000; + offset 0.150000 0.000000; + advance 0.400000; +}; +glyph 34 +{ + texcoords 0.115234 0.945312 0.126953 0.964844; + size 0.300000 0.250000; + offset 0.100000 0.500000; + advance 0.500000; +}; +glyph 35 +{ + texcoords 0.156250 0.906250 0.183594 0.964844; + size 0.700000 0.750000; + offset 0.100000 0.000000; + advance 0.850000; +}; +glyph 36 +{ + texcoords 0.208984 0.894531 0.228516 0.964844; + size 0.500000 0.900000; + offset 0.100000 -0.150000; + advance 0.650000; +}; +glyph 37 +{ + texcoords 0.251953 0.906250 0.285156 0.964844; + size 0.850000 0.750000; + offset 0.000000 0.000000; + advance 0.950000; +}; +glyph 38 +{ + texcoords 0.302734 0.906250 0.330078 0.964844; + size 0.700000 0.750000; + offset 0.050000 0.000000; + advance 0.750000; +}; +glyph 39 +{ + texcoords 0.363281 0.945312 0.367188 0.964844; + size 0.100000 0.250000; + offset 0.100000 0.500000; + advance 0.300000; +}; +glyph 40 +{ + texcoords 0.410156 0.894531 0.417969 0.964844; + size 0.200000 0.900000; + offset 0.100000 -0.150000; + advance 0.400000; +}; +glyph 41 +{ + texcoords 0.458984 0.894531 0.466797 0.964844; + size 0.200000 0.900000; + offset 0.100000 -0.150000; + advance 0.400000; +}; +glyph 42 +{ + texcoords 0.503906 0.925781 0.521484 0.964844; + size 0.450000 0.500000; + offset 0.000000 0.250000; + advance 0.500000; +}; +glyph 43 +{ + texcoords 0.548828 0.906250 0.572266 0.953125; + size 0.600000 0.600000; + offset 0.100000 0.000000; + advance 0.850000; +}; +glyph 44 +{ + texcoords 0.607422 0.894531 0.613281 0.914062; + size 0.150000 0.250000; + offset 0.050000 -0.150000; + advance 0.300000; +}; +glyph 45 +{ + texcoords 0.654297 0.925781 0.664062 0.933594; + size 0.250000 0.100000; + offset 0.050000 0.250000; + advance 0.350000; +}; +glyph 46 +{ + texcoords 0.705078 0.906250 0.708984 0.914062; + size 0.100000 0.100000; + offset 0.100000 0.000000; + advance 0.300000; +}; +glyph 47 +{ + texcoords 0.750000 0.902344 0.763672 0.964844; + size 0.350000 0.800000; + offset 0.000000 -0.050000; + advance 0.350000; +}; +glyph 48 +{ + texcoords 0.794922 0.906250 0.814453 0.964844; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 49 +{ + texcoords 0.845703 0.906250 0.863281 0.964844; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 50 +{ + texcoords 0.892578 0.906250 0.912109 0.964844; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 51 +{ + texcoords 0.941406 0.906250 0.960938 0.964844; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 52 +{ + texcoords 0.013672 0.808594 0.035156 0.867188; + size 0.550000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 53 +{ + texcoords 0.064453 0.808594 0.082031 0.867188; + size 0.450000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 54 +{ + texcoords 0.111328 0.808594 0.130859 0.867188; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 55 +{ + texcoords 0.160156 0.808594 0.179688 0.867188; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 56 +{ + texcoords 0.208984 0.808594 0.228516 0.867188; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 57 +{ + texcoords 0.257812 0.808594 0.277344 0.867188; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 58 +{ + texcoords 0.314453 0.808594 0.318359 0.847656; + size 0.100000 0.500000; + offset 0.100000 0.000000; + advance 0.350000; +}; +glyph 59 +{ + texcoords 0.363281 0.796875 0.369141 0.847656; + size 0.150000 0.650000; + offset 0.050000 -0.150000; + advance 0.350000; +}; +glyph 60 +{ + texcoords 0.402344 0.812500 0.427734 0.855469; + size 0.650000 0.550000; + offset 0.100000 0.050000; + advance 0.850000; +}; +glyph 61 +{ + texcoords 0.451172 0.820312 0.476562 0.843750; + size 0.650000 0.300000; + offset 0.100000 0.150000; + advance 0.850000; +}; +glyph 62 +{ + texcoords 0.500000 0.812500 0.525391 0.855469; + size 0.650000 0.550000; + offset 0.100000 0.050000; + advance 0.850000; +}; +glyph 63 +{ + texcoords 0.552734 0.808594 0.568359 0.867188; + size 0.400000 0.750000; + offset 0.050000 0.000000; + advance 0.550000; +}; +glyph 64 +{ + texcoords 0.591797 0.796875 0.626953 0.867188; + size 0.900000 0.900000; + offset 0.050000 -0.150000; + advance 1.000000; +}; +glyph 65 +{ + texcoords 0.646484 0.808594 0.671875 0.867188; + size 0.650000 0.750000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 66 +{ + texcoords 0.697266 0.808594 0.716797 0.867188; + size 0.500000 0.750000; + offset 0.100000 0.000000; + advance 0.700000; +}; +glyph 67 +{ + texcoords 0.744141 0.808594 0.767578 0.867188; + size 0.600000 0.750000; + offset 0.050000 0.000000; + advance 0.700000; +}; +glyph 68 +{ + texcoords 0.792969 0.808594 0.816406 0.867188; + size 0.600000 0.750000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 69 +{ + texcoords 0.845703 0.808594 0.863281 0.867188; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 70 +{ + texcoords 0.894531 0.808594 0.910156 0.867188; + size 0.400000 0.750000; + offset 0.100000 0.000000; + advance 0.600000; +}; +glyph 71 +{ + texcoords 0.939453 0.808594 0.964844 0.867188; + size 0.650000 0.750000; + offset 0.050000 0.000000; + advance 0.800000; +}; +glyph 72 +{ + texcoords 0.013672 0.710938 0.035156 0.769531; + size 0.550000 0.750000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 73 +{ + texcoords 0.070312 0.710938 0.074219 0.769531; + size 0.100000 0.750000; + offset 0.100000 0.000000; + advance 0.300000; +}; +glyph 74 +{ + texcoords 0.117188 0.695312 0.126953 0.769531; + size 0.250000 0.950000; + offset -0.050000 -0.200000; + advance 0.300000; +}; +glyph 75 +{ + texcoords 0.158203 0.710938 0.181641 0.769531; + size 0.600000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 76 +{ + texcoords 0.210938 0.710938 0.228516 0.769531; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.550000; +}; +glyph 77 +{ + texcoords 0.255859 0.710938 0.281250 0.769531; + size 0.650000 0.750000; + offset 0.100000 0.000000; + advance 0.850000; +}; +glyph 78 +{ + texcoords 0.306641 0.710938 0.328125 0.769531; + size 0.550000 0.750000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 79 +{ + texcoords 0.351562 0.710938 0.378906 0.769531; + size 0.700000 0.750000; + offset 0.050000 0.000000; + advance 0.800000; +}; +glyph 80 +{ + texcoords 0.406250 0.710938 0.423828 0.769531; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.600000; +}; +glyph 81 +{ + texcoords 0.449219 0.699219 0.476562 0.769531; + size 0.700000 0.900000; + offset 0.050000 -0.150000; + advance 0.800000; +}; +glyph 82 +{ + texcoords 0.501953 0.710938 0.523438 0.769531; + size 0.550000 0.750000; + offset 0.100000 0.000000; + advance 0.700000; +}; +glyph 83 +{ + texcoords 0.550781 0.710938 0.572266 0.769531; + size 0.550000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 84 +{ + texcoords 0.597656 0.710938 0.621094 0.769531; + size 0.600000 0.750000; + offset 0.000000 0.000000; + advance 0.600000; +}; +glyph 85 +{ + texcoords 0.648438 0.710938 0.669922 0.769531; + size 0.550000 0.750000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 86 +{ + texcoords 0.695312 0.710938 0.720703 0.769531; + size 0.650000 0.750000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 87 +{ + texcoords 0.738281 0.710938 0.773438 0.769531; + size 0.900000 0.750000; + offset 0.050000 0.000000; + advance 1.000000; +}; +glyph 88 +{ + texcoords 0.792969 0.710938 0.816406 0.769531; + size 0.600000 0.750000; + offset 0.050000 0.000000; + advance 0.700000; +}; +glyph 89 +{ + texcoords 0.841797 0.710938 0.865234 0.769531; + size 0.600000 0.750000; + offset 0.000000 0.000000; + advance 0.600000; +}; +glyph 90 +{ + texcoords 0.890625 0.710938 0.914062 0.769531; + size 0.600000 0.750000; + offset 0.050000 0.000000; + advance 0.700000; +}; +glyph 91 +{ + texcoords 0.947266 0.699219 0.955078 0.769531; + size 0.200000 0.900000; + offset 0.100000 -0.150000; + advance 0.400000; +}; +glyph 92 +{ + texcoords 0.017578 0.609375 0.031250 0.671875; + size 0.350000 0.800000; + offset 0.000000 -0.050000; + advance 0.350000; +}; +glyph 93 +{ + texcoords 0.068359 0.601562 0.076172 0.671875; + size 0.200000 0.900000; + offset 0.100000 -0.150000; + advance 0.400000; +}; +glyph 94 +{ + texcoords 0.109375 0.652344 0.134766 0.671875; + size 0.650000 0.250000; + offset 0.100000 0.500000; + advance 0.850000; +}; +glyph 95 +{ + texcoords 0.160156 0.593750 0.179688 0.601562; + size 0.500000 0.100000; + offset 0.000000 -0.250000; + advance 0.500000; +}; +glyph 96 +{ + texcoords 0.214844 0.660156 0.224609 0.675781; + size 0.250000 0.200000; + offset 0.050000 0.600000; + advance 0.500000; +}; +glyph 97 +{ + texcoords 0.259766 0.613281 0.277344 0.656250; + size 0.450000 0.550000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 98 +{ + texcoords 0.306641 0.613281 0.326172 0.671875; + size 0.500000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 99 +{ + texcoords 0.357422 0.613281 0.375000 0.656250; + size 0.450000 0.550000; + offset 0.050000 0.000000; + advance 0.550000; +}; +glyph 100 +{ + texcoords 0.404297 0.613281 0.423828 0.671875; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.650000; +}; +glyph 101 +{ + texcoords 0.453125 0.613281 0.472656 0.656250; + size 0.500000 0.550000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 102 +{ + texcoords 0.505859 0.613281 0.519531 0.671875; + size 0.350000 0.750000; + offset 0.000000 0.000000; + advance 0.350000; +}; +glyph 103 +{ + texcoords 0.550781 0.597656 0.570312 0.656250; + size 0.500000 0.750000; + offset 0.050000 -0.200000; + advance 0.650000; +}; +glyph 104 +{ + texcoords 0.601562 0.613281 0.619141 0.671875; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 105 +{ + texcoords 0.656250 0.613281 0.660156 0.671875; + size 0.100000 0.750000; + offset 0.100000 0.000000; + advance 0.300000; +}; +glyph 106 +{ + texcoords 0.703125 0.597656 0.710938 0.671875; + size 0.200000 0.950000; + offset 0.000000 -0.200000; + advance 0.300000; +}; +glyph 107 +{ + texcoords 0.746094 0.613281 0.765625 0.671875; + size 0.500000 0.750000; + offset 0.100000 0.000000; + advance 0.600000; +}; +glyph 108 +{ + texcoords 0.802734 0.613281 0.806641 0.671875; + size 0.100000 0.750000; + offset 0.100000 0.000000; + advance 0.300000; +}; +glyph 109 +{ + texcoords 0.837891 0.613281 0.869141 0.656250; + size 0.800000 0.550000; + offset 0.100000 0.000000; + advance 1.000000; +}; +glyph 110 +{ + texcoords 0.894531 0.613281 0.912109 0.656250; + size 0.450000 0.550000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 111 +{ + texcoords 0.941406 0.613281 0.960938 0.656250; + size 0.500000 0.550000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 112 +{ + texcoords 0.013672 0.500000 0.033203 0.558594; + size 0.500000 0.750000; + offset 0.100000 -0.200000; + advance 0.650000; +}; +glyph 113 +{ + texcoords 0.062500 0.500000 0.082031 0.558594; + size 0.500000 0.750000; + offset 0.050000 -0.200000; + advance 0.650000; +}; +glyph 114 +{ + texcoords 0.115234 0.515625 0.126953 0.558594; + size 0.300000 0.550000; + offset 0.100000 0.000000; + advance 0.400000; +}; +glyph 115 +{ + texcoords 0.162109 0.515625 0.179688 0.558594; + size 0.450000 0.550000; + offset 0.050000 0.000000; + advance 0.500000; +}; +glyph 116 +{ + texcoords 0.212891 0.515625 0.226562 0.570312; + size 0.350000 0.700000; + offset 0.050000 0.000000; + advance 0.400000; +}; +glyph 117 +{ + texcoords 0.259766 0.515625 0.277344 0.558594; + size 0.450000 0.550000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 118 +{ + texcoords 0.306641 0.515625 0.328125 0.558594; + size 0.550000 0.550000; + offset 0.000000 0.000000; + advance 0.550000; +}; +glyph 119 +{ + texcoords 0.351562 0.515625 0.380859 0.558594; + size 0.750000 0.550000; + offset 0.050000 0.000000; + advance 0.850000; +}; +glyph 120 +{ + texcoords 0.404297 0.515625 0.425781 0.558594; + size 0.550000 0.550000; + offset 0.000000 0.000000; + advance 0.550000; +}; +glyph 121 +{ + texcoords 0.453125 0.500000 0.474609 0.558594; + size 0.550000 0.750000; + offset 0.000000 -0.200000; + advance 0.550000; +}; +glyph 122 +{ + texcoords 0.503906 0.515625 0.521484 0.558594; + size 0.450000 0.550000; + offset 0.050000 0.000000; + advance 0.550000; +}; +glyph 123 +{ + texcoords 0.552734 0.503906 0.568359 0.574219; + size 0.400000 0.900000; + offset 0.150000 -0.150000; + advance 0.650000; +}; +glyph 124 +{ + texcoords 0.607422 0.496094 0.611328 0.574219; + size 0.100000 1.000000; + offset 0.150000 -0.250000; + advance 0.350000; +}; +glyph 125 +{ + texcoords 0.650391 0.503906 0.666016 0.574219; + size 0.400000 0.900000; + offset 0.100000 -0.150000; + advance 0.650000; +}; +glyph 126 +{ + texcoords 0.695312 0.531250 0.720703 0.550781; + size 0.650000 0.250000; + offset 0.100000 0.200000; + advance 0.850000; +}; +glyph 160 +{ + texcoords 0.755859 0.515625 0.755859 0.515625; + size 0.000000 0.000000; + offset 0.000000 0.000000; + advance 0.300000; +}; +glyph 161 +{ + texcoords 0.802734 0.515625 0.806641 0.574219; + size 0.100000 0.750000; + offset 0.150000 0.000000; + advance 0.400000; +}; +glyph 162 +{ + texcoords 0.845703 0.503906 0.863281 0.570312; + size 0.450000 0.850000; + offset 0.100000 -0.150000; + advance 0.650000; +}; +glyph 163 +{ + texcoords 0.894531 0.515625 0.912109 0.574219; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 164 +{ + texcoords 0.941406 0.519531 0.962891 0.562500; + size 0.550000 0.550000; + offset 0.000000 0.050000; + advance 0.650000; +}; +glyph 165 +{ + texcoords 0.011719 0.417969 0.035156 0.476562; + size 0.600000 0.750000; + offset 0.000000 0.000000; + advance 0.650000; +}; +glyph 166 +{ + texcoords 0.070312 0.406250 0.074219 0.472656; + size 0.100000 0.850000; + offset 0.150000 -0.150000; + advance 0.350000; +}; +glyph 167 +{ + texcoords 0.113281 0.410156 0.128906 0.476562; + size 0.400000 0.850000; + offset 0.050000 -0.100000; + advance 0.500000; +}; +glyph 168 +{ + texcoords 0.164062 0.468750 0.175781 0.476562; + size 0.300000 0.100000; + offset 0.100000 0.650000; + advance 0.500000; +}; +glyph 169 +{ + texcoords 0.205078 0.417969 0.232422 0.476562; + size 0.700000 0.750000; + offset 0.150000 0.000000; + advance 1.000000; +}; +glyph 170 +{ + texcoords 0.259766 0.437500 0.277344 0.476562; + size 0.450000 0.500000; + offset 0.050000 0.250000; + advance 0.450000; +}; +glyph 171 +{ + texcoords 0.306641 0.421875 0.326172 0.457031; + size 0.500000 0.450000; + offset 0.100000 0.050000; + advance 0.600000; +}; +glyph 172 +{ + texcoords 0.353516 0.425781 0.378906 0.449219; + size 0.650000 0.300000; + offset 0.100000 0.100000; + advance 0.850000; +}; +glyph 173 +{ + texcoords 0.410156 0.437500 0.419922 0.445312; + size 0.250000 0.100000; + offset 0.050000 0.250000; + advance 0.350000; +}; +glyph 174 +{ + texcoords 0.449219 0.417969 0.478516 0.476562; + size 0.750000 0.750000; + offset 0.150000 0.000000; + advance 1.000000; +}; +glyph 175 +{ + texcoords 0.505859 0.468750 0.517578 0.476562; + size 0.300000 0.100000; + offset 0.100000 0.650000; + advance 0.500000; +}; +glyph 176 +{ + texcoords 0.554688 0.453125 0.566406 0.476562; + size 0.300000 0.300000; + offset 0.100000 0.450000; + advance 0.500000; +}; +glyph 177 +{ + texcoords 0.597656 0.417969 0.621094 0.468750; + size 0.600000 0.650000; + offset 0.150000 0.000000; + advance 0.850000; +}; +glyph 178 +{ + texcoords 0.652344 0.445312 0.664062 0.476562; + size 0.300000 0.400000; + offset 0.050000 0.350000; + advance 0.400000; +}; +glyph 179 +{ + texcoords 0.701172 0.445312 0.712891 0.476562; + size 0.300000 0.400000; + offset 0.050000 0.350000; + advance 0.400000; +}; +glyph 180 +{ + texcoords 0.751953 0.464844 0.761719 0.480469; + size 0.250000 0.200000; + offset 0.150000 0.600000; + advance 0.500000; +}; +glyph 181 +{ + texcoords 0.794922 0.402344 0.814453 0.460938; + size 0.500000 0.750000; + offset 0.100000 -0.200000; + advance 0.650000; +}; +glyph 182 +{ + texcoords 0.845703 0.410156 0.863281 0.476562; + size 0.450000 0.850000; + offset 0.100000 -0.100000; + advance 0.650000; +}; +glyph 183 +{ + texcoords 0.900391 0.441406 0.904297 0.449219; + size 0.100000 0.100000; + offset 0.100000 0.300000; + advance 0.300000; +}; +glyph 184 +{ + texcoords 0.947266 0.402344 0.955078 0.417969; + size 0.200000 0.200000; + offset 0.150000 -0.200000; + advance 0.500000; +}; +glyph 185 +{ + texcoords 0.019531 0.347656 0.029297 0.378906; + size 0.250000 0.400000; + offset 0.100000 0.350000; + advance 0.400000; +}; +glyph 186 +{ + texcoords 0.064453 0.339844 0.080078 0.378906; + size 0.400000 0.500000; + offset 0.050000 0.250000; + advance 0.450000; +}; +glyph 187 +{ + texcoords 0.111328 0.324219 0.130859 0.359375; + size 0.500000 0.450000; + offset 0.100000 0.050000; + advance 0.600000; +}; +glyph 188 +{ + texcoords 0.154297 0.320312 0.185547 0.378906; + size 0.800000 0.750000; + offset 0.100000 0.000000; + advance 0.950000; +}; +glyph 189 +{ + texcoords 0.203125 0.320312 0.234375 0.378906; + size 0.800000 0.750000; + offset 0.100000 0.000000; + advance 0.950000; +}; +glyph 190 +{ + texcoords 0.251953 0.320312 0.285156 0.378906; + size 0.850000 0.750000; + offset 0.050000 0.000000; + advance 0.950000; +}; +glyph 191 +{ + texcoords 0.308594 0.320312 0.324219 0.378906; + size 0.400000 0.750000; + offset 0.050000 0.000000; + advance 0.550000; +}; +glyph 192 +{ + texcoords 0.353516 0.320312 0.378906 0.394531; + size 0.650000 0.950000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 193 +{ + texcoords 0.402344 0.320312 0.427734 0.394531; + size 0.650000 0.950000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 194 +{ + texcoords 0.451172 0.320312 0.476562 0.394531; + size 0.650000 0.950000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 195 +{ + texcoords 0.500000 0.320312 0.525391 0.390625; + size 0.650000 0.900000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 196 +{ + texcoords 0.548828 0.320312 0.574219 0.394531; + size 0.650000 0.950000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 197 +{ + texcoords 0.597656 0.320312 0.623047 0.394531; + size 0.650000 0.950000; + offset 0.000000 0.000000; + advance 0.700000; +}; +glyph 198 +{ + texcoords 0.640625 0.320312 0.675781 0.378906; + size 0.900000 0.750000; + offset 0.000000 0.000000; + advance 1.000000; +}; +glyph 199 +{ + texcoords 0.695312 0.304688 0.718750 0.378906; + size 0.600000 0.950000; + offset 0.050000 -0.200000; + advance 0.700000; +}; +glyph 200 +{ + texcoords 0.748047 0.320312 0.765625 0.394531; + size 0.450000 0.950000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 201 +{ + texcoords 0.796875 0.320312 0.814453 0.394531; + size 0.450000 0.950000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 202 +{ + texcoords 0.845703 0.320312 0.863281 0.394531; + size 0.450000 0.950000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 203 +{ + texcoords 0.894531 0.320312 0.912109 0.394531; + size 0.450000 0.950000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 204 +{ + texcoords 0.947266 0.320312 0.955078 0.394531; + size 0.200000 0.950000; + offset 0.050000 0.000000; + advance 0.300000; +}; +glyph 205 +{ + texcoords 0.019531 0.222656 0.027344 0.296875; + size 0.200000 0.950000; + offset 0.100000 0.000000; + advance 0.300000; +}; +glyph 206 +{ + texcoords 0.066406 0.222656 0.078125 0.296875; + size 0.300000 0.950000; + offset 0.000000 0.000000; + advance 0.300000; +}; +glyph 207 +{ + texcoords 0.115234 0.222656 0.126953 0.296875; + size 0.300000 0.950000; + offset 0.000000 0.000000; + advance 0.300000; +}; +glyph 208 +{ + texcoords 0.156250 0.222656 0.183594 0.281250; + size 0.700000 0.750000; + offset 0.000000 0.000000; + advance 0.750000; +}; +glyph 209 +{ + texcoords 0.208984 0.222656 0.230469 0.292969; + size 0.550000 0.900000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 210 +{ + texcoords 0.253906 0.222656 0.281250 0.296875; + size 0.700000 0.950000; + offset 0.050000 0.000000; + advance 0.800000; +}; +glyph 211 +{ + texcoords 0.302734 0.222656 0.330078 0.296875; + size 0.700000 0.950000; + offset 0.050000 0.000000; + advance 0.800000; +}; +glyph 212 +{ + texcoords 0.351562 0.222656 0.378906 0.296875; + size 0.700000 0.950000; + offset 0.050000 0.000000; + advance 0.800000; +}; +glyph 213 +{ + texcoords 0.400391 0.222656 0.427734 0.292969; + size 0.700000 0.900000; + offset 0.050000 0.000000; + advance 0.800000; +}; +glyph 214 +{ + texcoords 0.449219 0.222656 0.476562 0.296875; + size 0.700000 0.950000; + offset 0.050000 0.000000; + advance 0.800000; +}; +glyph 215 +{ + texcoords 0.501953 0.226562 0.523438 0.269531; + size 0.550000 0.550000; + offset 0.150000 0.050000; + advance 0.850000; +}; +glyph 216 +{ + texcoords 0.544922 0.218750 0.576172 0.285156; + size 0.800000 0.850000; + offset 0.000000 -0.050000; + advance 0.800000; +}; +glyph 217 +{ + texcoords 0.599609 0.222656 0.621094 0.296875; + size 0.550000 0.950000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 218 +{ + texcoords 0.648438 0.222656 0.669922 0.296875; + size 0.550000 0.950000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 219 +{ + texcoords 0.697266 0.222656 0.718750 0.296875; + size 0.550000 0.950000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 220 +{ + texcoords 0.746094 0.222656 0.767578 0.296875; + size 0.550000 0.950000; + offset 0.100000 0.000000; + advance 0.750000; +}; +glyph 221 +{ + texcoords 0.792969 0.222656 0.816406 0.296875; + size 0.600000 0.950000; + offset 0.000000 0.000000; + advance 0.600000; +}; +glyph 222 +{ + texcoords 0.845703 0.222656 0.863281 0.281250; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.600000; +}; +glyph 223 +{ + texcoords 0.892578 0.222656 0.912109 0.281250; + size 0.500000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 224 +{ + texcoords 0.943359 0.222656 0.960938 0.285156; + size 0.450000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 225 +{ + texcoords 0.015625 0.125000 0.033203 0.187500; + size 0.450000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 226 +{ + texcoords 0.064453 0.125000 0.082031 0.187500; + size 0.450000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 227 +{ + texcoords 0.113281 0.125000 0.130859 0.187500; + size 0.450000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 228 +{ + texcoords 0.162109 0.125000 0.179688 0.183594; + size 0.450000 0.750000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 229 +{ + texcoords 0.210938 0.125000 0.228516 0.191406; + size 0.450000 0.850000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 230 +{ + texcoords 0.251953 0.125000 0.285156 0.167969; + size 0.850000 0.550000; + offset 0.050000 0.000000; + advance 0.950000; +}; +glyph 231 +{ + texcoords 0.308594 0.109375 0.326172 0.167969; + size 0.450000 0.750000; + offset 0.050000 -0.200000; + advance 0.550000; +}; +glyph 232 +{ + texcoords 0.355469 0.125000 0.375000 0.187500; + size 0.500000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 233 +{ + texcoords 0.404297 0.125000 0.423828 0.187500; + size 0.500000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 234 +{ + texcoords 0.453125 0.125000 0.472656 0.187500; + size 0.500000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 235 +{ + texcoords 0.501953 0.125000 0.521484 0.183594; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 236 +{ + texcoords 0.556641 0.125000 0.566406 0.187500; + size 0.250000 0.800000; + offset -0.050000 0.000000; + advance 0.300000; +}; +glyph 237 +{ + texcoords 0.605469 0.125000 0.615234 0.187500; + size 0.250000 0.800000; + offset 0.050000 0.000000; + advance 0.300000; +}; +glyph 238 +{ + texcoords 0.652344 0.125000 0.664062 0.187500; + size 0.300000 0.800000; + offset 0.000000 0.000000; + advance 0.300000; +}; +glyph 239 +{ + texcoords 0.701172 0.125000 0.712891 0.183594; + size 0.300000 0.750000; + offset 0.000000 0.000000; + advance 0.300000; +}; +glyph 240 +{ + texcoords 0.746094 0.125000 0.765625 0.183594; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 241 +{ + texcoords 0.796875 0.125000 0.814453 0.187500; + size 0.450000 0.800000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 242 +{ + texcoords 0.843750 0.125000 0.863281 0.187500; + size 0.500000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 243 +{ + texcoords 0.892578 0.125000 0.912109 0.187500; + size 0.500000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 244 +{ + texcoords 0.941406 0.125000 0.960938 0.187500; + size 0.500000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 245 +{ + texcoords 0.013672 0.027344 0.033203 0.089844; + size 0.500000 0.800000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 246 +{ + texcoords 0.062500 0.027344 0.082031 0.085938; + size 0.500000 0.750000; + offset 0.050000 0.000000; + advance 0.600000; +}; +glyph 247 +{ + texcoords 0.109375 0.031250 0.132812 0.070312; + size 0.600000 0.500000; + offset 0.100000 0.050000; + advance 0.850000; +}; +glyph 248 +{ + texcoords 0.158203 0.023438 0.181641 0.074219; + size 0.600000 0.650000; + offset 0.000000 -0.050000; + advance 0.600000; +}; +glyph 249 +{ + texcoords 0.210938 0.027344 0.228516 0.089844; + size 0.450000 0.800000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 250 +{ + texcoords 0.259766 0.027344 0.277344 0.089844; + size 0.450000 0.800000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 251 +{ + texcoords 0.308594 0.027344 0.326172 0.089844; + size 0.450000 0.800000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 252 +{ + texcoords 0.357422 0.027344 0.375000 0.085938; + size 0.450000 0.750000; + offset 0.100000 0.000000; + advance 0.650000; +}; +glyph 253 +{ + texcoords 0.404297 0.011719 0.425781 0.089844; + size 0.550000 1.000000; + offset 0.000000 -0.200000; + advance 0.550000; +}; +glyph 254 +{ + texcoords 0.453125 0.011719 0.472656 0.085938; + size 0.500000 0.950000; + offset 0.100000 -0.200000; + advance 0.650000; +}; +glyph 255 +{ + texcoords 0.501953 0.011719 0.523438 0.085938; + size 0.550000 0.950000; + offset 0.000000 -0.200000; + advance 0.550000; +}; diff --git a/dejavu-20.png b/dejavu-20.png new file mode 100644 index 0000000..08251db Binary files /dev/null and b/dejavu-20.png differ diff --git a/digitalreadout-16.font b/digitalreadout-16.font new file mode 100644 index 0000000..2828761 --- /dev/null +++ b/digitalreadout-16.font @@ -0,0 +1,669 @@ +texture "digitalreadout-16.png"; +default_size 16; +ascent 0.812; +descent 0.062; +glyph 32 +{ + texcoords 0.031250 0.898438 0.031250 0.898438; + size 0.000 0.000; + offset 0.000 0.000; + advance 0.438; +}; +glyph 33 +{ + texcoords 0.085938 0.898438 0.101562 0.984375; + size 0.250 0.688; + offset 0.000 0.000; + advance 0.125; +}; +glyph 34 +{ + texcoords 0.148438 0.968750 0.160156 0.992188; + size 0.188 0.188; + offset 0.125 0.562; + advance 0.188; +}; +glyph 35 +{ + texcoords 0.199219 0.898438 0.234375 0.992188; + size 0.562 0.750; + offset 0.000 0.000; + advance 0.438; +}; +glyph 36 +{ + texcoords 0.265625 0.882812 0.292969 1.000000; + size 0.438 0.938; + offset 0.062 -0.125; + advance 0.438; +}; +glyph 37 +{ + texcoords 0.324219 0.898438 0.359375 0.992188; + size 0.562 0.750; + offset 0.000 0.000; + advance 0.438; +}; +glyph 38 +{ + texcoords 0.390625 0.898438 0.421875 0.984375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 39 +{ + texcoords 0.464844 0.968750 0.472656 0.984375; + size 0.125 0.125; + offset 0.125 0.562; + advance 0.125; +}; +glyph 40 +{ + texcoords 0.519531 0.898438 0.542969 0.984375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.250; +}; +glyph 41 +{ + texcoords 0.582031 0.898438 0.605469 0.984375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.250; +}; +glyph 42 +{ + texcoords 0.640625 0.906250 0.667969 0.976562; + size 0.438 0.562; + offset 0.062 0.062; + advance 0.438; +}; +glyph 43 +{ + texcoords 0.707031 0.906250 0.726562 0.976562; + size 0.312 0.562; + offset 0.125 0.062; + advance 0.438; +}; +glyph 44 +{ + texcoords 0.777344 0.890625 0.785156 0.906250; + size 0.125 0.125; + offset 0.000 -0.062; + advance 0.125; +}; +glyph 45 +{ + texcoords 0.832031 0.937500 0.851562 0.945312; + size 0.312 0.062; + offset 0.125 0.312; + advance 0.438; +}; +glyph 46 +{ + texcoords 0.902344 0.898438 0.910156 0.914062; + size 0.125 0.125; + offset 0.000 0.000; + advance 0.125; +}; +glyph 47 +{ + texcoords 0.953125 0.906250 0.980469 0.976562; + size 0.438 0.562; + offset 0.062 0.062; + advance 0.438; +}; +glyph 48 +{ + texcoords 0.011719 0.773438 0.046875 0.859375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 49 +{ + texcoords 0.085938 0.781250 0.101562 0.859375; + size 0.250 0.625; + offset 0.312 0.062; + advance 0.438; +}; +glyph 50 +{ + texcoords 0.136719 0.773438 0.171875 0.859375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 51 +{ + texcoords 0.203125 0.773438 0.234375 0.859375; + size 0.500 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 52 +{ + texcoords 0.265625 0.781250 0.296875 0.859375; + size 0.500 0.625; + offset 0.062 0.062; + advance 0.438; +}; +glyph 53 +{ + texcoords 0.328125 0.773438 0.355469 0.859375; + size 0.438 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 54 +{ + texcoords 0.390625 0.773438 0.421875 0.859375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 55 +{ + texcoords 0.457031 0.781250 0.480469 0.859375; + size 0.375 0.625; + offset 0.188 0.062; + advance 0.438; +}; +glyph 56 +{ + texcoords 0.511719 0.773438 0.546875 0.859375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 57 +{ + texcoords 0.578125 0.773438 0.609375 0.859375; + size 0.500 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 58 +{ + texcoords 0.632812 0.773438 0.675781 0.812500; + size 0.688 0.312; + offset -0.250 0.000; + advance 0.125; +}; +glyph 59 +{ + texcoords 0.695312 0.765625 0.738281 0.812500; + size 0.688 0.375; + offset -0.250 -0.062; + advance 0.125; +}; +glyph 60 +{ + texcoords 0.773438 0.781250 0.789062 0.851562; + size 0.250 0.562; + offset 0.250 0.062; + advance 0.438; +}; +glyph 61 +{ + texcoords 0.828125 0.804688 0.855469 0.828125; + size 0.438 0.188; + offset 0.062 0.250; + advance 0.438; +}; +glyph 62 +{ + texcoords 0.898438 0.781250 0.914062 0.851562; + size 0.250 0.562; + offset 0.250 0.062; + advance 0.438; +}; +glyph 63 +{ + texcoords 0.949219 0.773438 0.984375 0.859375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 64 +{ + texcoords 0.011719 0.648438 0.046875 0.742188; + size 0.562 0.750; + offset 0.000 0.000; + advance 0.438; +}; +glyph 65 +{ + texcoords 0.074219 0.656250 0.109375 0.734375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 66 +{ + texcoords 0.140625 0.648438 0.171875 0.734375; + size 0.500 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 67 +{ + texcoords 0.203125 0.648438 0.234375 0.734375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 68 +{ + texcoords 0.265625 0.648438 0.296875 0.734375; + size 0.500 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 69 +{ + texcoords 0.328125 0.648438 0.359375 0.734375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 70 +{ + texcoords 0.390625 0.656250 0.421875 0.734375; + size 0.500 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 71 +{ + texcoords 0.453125 0.648438 0.484375 0.734375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 72 +{ + texcoords 0.511719 0.656250 0.546875 0.734375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 73 +{ + texcoords 0.585938 0.656250 0.597656 0.726562; + size 0.188 0.562; + offset 0.188 0.062; + advance 0.438; +}; +glyph 74 +{ + texcoords 0.636719 0.648438 0.671875 0.734375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 75 +{ + texcoords 0.703125 0.648438 0.734375 0.734375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 76 +{ + texcoords 0.769531 0.648438 0.792969 0.734375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 77 +{ + texcoords 0.824219 0.656250 0.859375 0.734375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 78 +{ + texcoords 0.886719 0.656250 0.921875 0.734375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 79 +{ + texcoords 0.949219 0.648438 0.984375 0.734375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 80 +{ + texcoords 0.011719 0.531250 0.046875 0.609375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 81 +{ + texcoords 0.074219 0.523438 0.109375 0.609375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 82 +{ + texcoords 0.136719 0.531250 0.171875 0.609375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 83 +{ + texcoords 0.203125 0.523438 0.230469 0.609375; + size 0.438 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 84 +{ + texcoords 0.269531 0.531250 0.289062 0.609375; + size 0.312 0.625; + offset 0.188 0.062; + advance 0.438; +}; +glyph 85 +{ + texcoords 0.324219 0.523438 0.359375 0.609375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 86 +{ + texcoords 0.390625 0.531250 0.417969 0.609375; + size 0.438 0.625; + offset 0.125 0.062; + advance 0.438; +}; +glyph 87 +{ + texcoords 0.449219 0.531250 0.484375 0.609375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 88 +{ + texcoords 0.515625 0.531250 0.542969 0.601562; + size 0.438 0.562; + offset 0.062 0.062; + advance 0.438; +}; +glyph 89 +{ + texcoords 0.578125 0.531250 0.609375 0.609375; + size 0.500 0.625; + offset 0.062 0.062; + advance 0.438; +}; +glyph 90 +{ + texcoords 0.640625 0.523438 0.667969 0.609375; + size 0.438 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 91 +{ + texcoords 0.707031 0.523438 0.730469 0.609375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.250; +}; +glyph 92 +{ + texcoords 0.769531 0.531250 0.789062 0.601562; + size 0.312 0.562; + offset 0.125 0.062; + advance 0.438; +}; +glyph 93 +{ + texcoords 0.832031 0.523438 0.855469 0.609375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.250; +}; +glyph 94 +{ + texcoords 0.894531 0.562500 0.914062 0.601562; + size 0.312 0.312; + offset 0.125 0.312; + advance 0.438; +}; +glyph 95 +{ + texcoords 0.949219 0.523438 0.984375 0.617188; + size 0.562 0.750; + offset 0.000 0.000; + advance 0.438; +}; +glyph 96 +{ + texcoords 0.011719 0.398438 0.046875 0.492188; + size 0.562 0.750; + offset 0.000 0.000; + advance 0.438; +}; +glyph 97 +{ + texcoords 0.074219 0.406250 0.109375 0.484375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 98 +{ + texcoords 0.140625 0.398438 0.171875 0.484375; + size 0.500 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 99 +{ + texcoords 0.203125 0.398438 0.234375 0.484375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 100 +{ + texcoords 0.265625 0.398438 0.296875 0.484375; + size 0.500 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 101 +{ + texcoords 0.328125 0.398438 0.359375 0.484375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 102 +{ + texcoords 0.390625 0.406250 0.421875 0.484375; + size 0.500 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 103 +{ + texcoords 0.453125 0.398438 0.484375 0.484375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 104 +{ + texcoords 0.511719 0.406250 0.546875 0.484375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 105 +{ + texcoords 0.585938 0.406250 0.597656 0.476562; + size 0.188 0.562; + offset 0.188 0.062; + advance 0.438; +}; +glyph 106 +{ + texcoords 0.636719 0.398438 0.671875 0.484375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 107 +{ + texcoords 0.703125 0.398438 0.734375 0.484375; + size 0.500 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 108 +{ + texcoords 0.769531 0.398438 0.792969 0.484375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 109 +{ + texcoords 0.824219 0.406250 0.859375 0.484375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 110 +{ + texcoords 0.886719 0.406250 0.921875 0.484375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 111 +{ + texcoords 0.949219 0.398438 0.984375 0.484375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 112 +{ + texcoords 0.011719 0.281250 0.046875 0.359375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 113 +{ + texcoords 0.074219 0.273438 0.109375 0.359375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 114 +{ + texcoords 0.136719 0.281250 0.171875 0.359375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 115 +{ + texcoords 0.203125 0.273438 0.230469 0.359375; + size 0.438 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 116 +{ + texcoords 0.269531 0.281250 0.289062 0.359375; + size 0.312 0.625; + offset 0.188 0.062; + advance 0.438; +}; +glyph 117 +{ + texcoords 0.324219 0.273438 0.359375 0.359375; + size 0.562 0.688; + offset 0.000 0.000; + advance 0.438; +}; +glyph 118 +{ + texcoords 0.390625 0.281250 0.417969 0.359375; + size 0.438 0.625; + offset 0.125 0.062; + advance 0.438; +}; +glyph 119 +{ + texcoords 0.449219 0.281250 0.484375 0.359375; + size 0.562 0.625; + offset 0.000 0.062; + advance 0.438; +}; +glyph 120 +{ + texcoords 0.515625 0.281250 0.542969 0.351562; + size 0.438 0.562; + offset 0.062 0.062; + advance 0.438; +}; +glyph 121 +{ + texcoords 0.578125 0.281250 0.609375 0.359375; + size 0.500 0.625; + offset 0.062 0.062; + advance 0.438; +}; +glyph 122 +{ + texcoords 0.640625 0.273438 0.667969 0.359375; + size 0.438 0.688; + offset 0.062 0.000; + advance 0.438; +}; +glyph 123 +{ + texcoords 0.707031 0.273438 0.730469 0.359375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.250; +}; +glyph 124 +{ + texcoords 0.773438 0.281250 0.789062 0.351562; + size 0.250 0.562; + offset 0.000 0.062; + advance 0.125; +}; +glyph 125 +{ + texcoords 0.832031 0.273438 0.855469 0.359375; + size 0.375 0.688; + offset 0.000 0.000; + advance 0.250; +}; +glyph 126 +{ + texcoords 0.886719 0.273438 0.921875 0.367188; + size 0.562 0.750; + offset 0.000 0.000; + advance 0.438; +}; diff --git a/digitalreadout-16.png b/digitalreadout-16.png new file mode 100644 index 0000000..e9f7684 Binary files /dev/null and b/digitalreadout-16.png differ diff --git a/engineer.res b/engineer.res new file mode 100644 index 0000000..191663f --- /dev/null +++ b/engineer.res @@ -0,0 +1,226 @@ +font "dejavu-12.font"; +font "digitalreadout-16.font"; + +texture "gui.png"; + +graphic "button" +{ + texture "gui"; + slice 8 112 21 10; + border { top 2; right 3; bottom 4; left 2; }; + shadow { top 0; right 1; bottom 2; left 0; }; +}; + +graphic "buttondown" +{ + texture "gui"; + slice 38 112 21 10; + border { top 2; right 3; bottom 4; left 2; }; + shadow { top 0; right 1; bottom 2; left 0; }; +}; + +graphic "greenbutton" +{ + texture "gui"; + slice 8 97 21 10; + border { top 2; right 3; bottom 4; left 2; }; + shadow { top 0; right 1; bottom 2; left 0; }; +}; + +graphic "greenbuttondown" +{ + texture "gui"; + slice 38 97 21 10; + border { top 2; right 3; bottom 4; left 2; }; + shadow { top 0; right 1; bottom 2; left 0; }; +}; + +graphic "redbutton" +{ + texture "gui"; + slice 8 82 21 10; + border { top 2; right 3; bottom 4; left 2; }; + shadow { top 0; right 1; bottom 2; left 0; }; +}; + +graphic "redbuttondown" +{ + texture "gui"; + slice 38 82 21 10; + border { top 2; right 3; bottom 4; left 2; }; + shadow { top 0; right 1; bottom 2; left 0; }; +}; + +graphic "panel" +{ + texture "gui"; + slice 8 158 30 20; + border { top 2; right 2; bottom 2; left 2; }; +}; + +graphic "greenlamp" +{ + texture "gui"; + slice 87 222 12 12; +}; + +graphic "greenlamplit" +{ + texture "gui"; + slice 87 236 12 12; +}; + +graphic "redlamp" +{ + texture "gui"; + slice 101 222 12 12; +}; + +graphic "redlamplit" +{ + texture "gui"; + slice 101 236 12 12; +}; + +graphic "digidisplay" +{ + texture "gui"; + slice 14 226 48 24; + border { top 5; right 5; bottom 5; left 5; }; +}; + +graphic "hsliderslot" +{ + texture "gui"; + slice 8 188 60 10; + border { top 0; right 5; bottom 0; left 5; }; +}; + +graphic "hslider" +{ + texture "gui"; + slice 73 105 32 13; + shadow { top 0; right 2; bottom 3; left 0; }; +}; + +style "button" "" +{ + font_color 0 0 0; + + part "button" + { + graphic normal "button"; + graphic active "buttondown"; + align 0 -1; + fill false false; + }; + + part "text" + { + align 0 1; + }; +}; + +style "button" "green" +{ + font_color 0 0 0; + + part "button" + { + graphic normal "greenbutton"; + graphic active "greenbuttondown"; + align 0 -1; + fill false false; + }; + + part "text" + { + align 0 1; + }; +}; + +style "button" "red" +{ + font_color 0 0 0; + + part "button" + { + graphic normal "redbutton"; + graphic active "redbuttondown"; + align 0 -1; + fill false false; + }; + + part "text" + { + align 0 1; + }; +}; + +style "panel" "" +{ + part "background" + { + graphic normal "panel"; + }; + part "children"; +}; + +style "indicator" ""; + +style "indicator" "green" +{ + part "lamp" + { + graphic normal "greenlamp"; + graphic active "greenlamplit"; + fill false false; + }; +}; + +style "indicator" "red" +{ + part "lamp" + { + graphic normal "redlamp"; + graphic active "redlamplit"; + fill false false; + }; +}; + +style "label" "" +{ + font_color 0 0 0; + part "text"; +}; + +style "label" "digital" +{ + font "digitalreadout-16"; + font_color 0.3 1 0.3; + + part "background" + { + graphic normal "digidisplay"; + }; + + part "text" + { + fill false false; + align 0 0; + }; +}; + +style "hslider" "" +{ + part "background" + { + graphic normal "hsliderslot"; + fill true false; + }; + + part "slider" + { + graphic normal "hslider"; + }; +}; diff --git a/gui.blend b/gui.blend new file mode 100644 index 0000000..f53efda Binary files /dev/null and b/gui.blend differ diff --git a/gui.png b/gui.png new file mode 100644 index 0000000..3457c02 Binary files /dev/null and b/gui.png differ diff --git a/source/3d/layout.cpp b/source/3d/layout.cpp new file mode 100644 index 0000000..b90f553 --- /dev/null +++ b/source/3d/layout.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include +#include "layout.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Layout3D::Layout3D(Layout &l): + layout(l), + quality(4) +{ + layout.signal_track_added.connect(sigc::mem_fun(this, &Layout3D::track_added)); + layout.signal_track_removed.connect(sigc::mem_fun(this, &Layout3D::track_removed)); +} + +Layout3D::~Layout3D() +{ + for(Track3DSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + delete *i; +} + +void Layout3D::set_quality(unsigned q) +{ + quality=q; + for(Track3DSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + (*i)->set_quality(quality); +} + +void Layout3D::render(bool endpoints) +{ + GL::Texture::unbind(); + glEnable(GL_DEPTH_TEST); + + for(Track3DSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + (*i)->render(); + + if(endpoints) + { + glDepthMask(false); + for(Track3DSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + (*i)->render_endpoints(); + glDepthMask(true); + } +} + +Track3D *Layout3D::get_track(const Track *t) +{ + for(Track3DSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + if(&(*i)->get_track()==t) + return *i; + + return 0; +} + +Track3D *Layout3D::pick_track(float x, float y, float size) +{ + vector select_buf; + GL::select_buffer(select_buf); + GL::render_mode(GL::SELECT); + + glPushMatrix(); + glLoadIdentity(); + + double clip[4]; + clip[0]=1; + clip[1]=0; + clip[2]=x-size; + clip[3]=0; + glClipPlane(GL_CLIP_PLANE0, clip); + glEnable(GL_CLIP_PLANE0); + + clip[0]=-1; + clip[2]=-(x+size); + glClipPlane(GL_CLIP_PLANE1, clip); + glEnable(GL_CLIP_PLANE1); + + clip[0]=0; + clip[1]=1; + clip[2]=y-size; + glClipPlane(GL_CLIP_PLANE2, clip); + glEnable(GL_CLIP_PLANE2); + + clip[1]=-1; + clip[2]=-(y+size); + glClipPlane(GL_CLIP_PLANE3, clip); + glEnable(GL_CLIP_PLANE3); + + glPopMatrix(); + + render(); + + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + + GL::render_mode(GL::RENDER); + Track3D *track=0; + unsigned track_depth=numeric_limits::max(); + for(vector::iterator i=select_buf.begin(); i!=select_buf.end(); ++i) + if(i->min_depth(i->names.back()); + track_depth=i->min_depth; + } + + return track; +} + +void Layout3D::track_added(Track *t) +{ + tracks.push_back(new Track3D(*t, quality)); +} + +void Layout3D::track_removed(Track *t) +{ + for(Track3DSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + if(&(*i)->get_track()==t) + { + delete *i; + tracks.erase(i); + return; + } +} + +} // namespace Marklin diff --git a/source/3d/layout.h b/source/3d/layout.h new file mode 100644 index 0000000..09189ed --- /dev/null +++ b/source/3d/layout.h @@ -0,0 +1,32 @@ +#ifndef MARKLIN3D_LAYOUT_H_ +#define MARKLIN3D_LAYOUT_H_ + +#include "libmarklin/layout.h" +#include "track.h" + +namespace Marklin { + +class Layout3D +{ +public: + Layout3D(Layout &); + ~Layout3D(); + + void set_quality(unsigned); + const Track3DSeq &get_tracks() const { return tracks; } + void render(bool =false); + Track3D *get_track(const Track *); + Track3D *pick_track(float, float, float); +private: + Layout &layout; + Track3DSeq tracks; + unsigned quality; + + void track_added(Track *); + void track_removed(Track *); +}; + +} // namespace Marklin + +#endif + diff --git a/source/3d/misc.h b/source/3d/misc.h new file mode 100644 index 0000000..8d77ee2 --- /dev/null +++ b/source/3d/misc.h @@ -0,0 +1,15 @@ +#ifndef MARKLIN3D_MISC_H_ +#define MARKLIN3D_MISC_H_ + +namespace Marklin { + +struct Color +{ + float r, g, b; + + Color(float r_, float g_, float b_): r(r_), g(g_), b(b_) { } +}; + +} // namespace Marklin + +#endif diff --git a/source/3d/track.cpp b/source/3d/track.cpp new file mode 100644 index 0000000..e64f42e --- /dev/null +++ b/source/3d/track.cpp @@ -0,0 +1,253 @@ +#include +#include +#include +#include "track.h" + +using namespace std; +using namespace Msp; + +#include + +namespace Marklin { + +Track3D::Track3D(Track &t, unsigned q): + track(t), + color(1, 1, 1), + varray((GL::NORMAL3, GL::VERTEX3)), + quality(q) +{ + build_object(); +} + +void Track3D::set_quality(unsigned q) +{ + quality=q; + build_object(); +} + +void Track3D::get_bounds(float angle, Point &minp, Point &maxp) const +{ + const Point &pos=track.get_position(); + float rot=track.get_rotation(); + + float c=cos(-angle); + float s=sin(-angle); + + minp.x=maxp.x=c*pos.x-s*pos.y; + minp.y=maxp.y=s*pos.x+c*pos.y; + + float c2=cos(rot-angle); + float s2=sin(rot-angle); + + for(vector::const_iterator i=border.begin(); i!=border.end(); ++i) + { + float x=c*pos.x-s*pos.y + c2*i->x-s2*i->y; + float y=s*pos.x+c*pos.y + s2*i->x+c2*i->y; + + minp.x=min(minp.x, x); + minp.y=min(minp.y, y); + maxp.x=max(maxp.x, x); + maxp.y=max(maxp.y, y); + } +} + +void Track3D::render() +{ + prepare_render(); + + glPushName((unsigned)this); + + varray.apply(); + glColor4f(0.25*color.r, 0.25*color.g, 0.25*color.b, 1); + glDrawElements(GL_QUADS, base_seq.size(), GL_UNSIGNED_INT, &base_seq[0]); + if(quality>1) + { + glColor4f(0.85*color.r, 0.85*color.g, 0.85*color.b, 1); + glDrawElements(GL_QUADS, rail_seq.size(), GL_UNSIGNED_INT, &rail_seq[0]); + } + + glPopName(); + glPopMatrix(); +} + +void Track3D::render_endpoints() +{ + prepare_render(); + + const Point &pos=track.get_position(); + const Track::EndpointSeq &endpoints=track.get_endpoints(); + for(Track::EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + { + GL::set(GL_CULL_FACE, i->link); + if(i->link) + glColor4f(0.5, 0, 1, 0.5); + else + glColor4f(1, 0, 0.5, 0.5); + + float c=cos(i->rot); + float s=sin(i->rot); + + glBegin(GL_QUADS); + glVertex3f(i->pos.x-s*0.025, i->pos.y+c*0.025, 0); + glVertex3f(i->pos.x+s*0.025, i->pos.y-c*0.025, 0); + glVertex3f(i->pos.x+s*0.025, i->pos.y-c*0.025, pos.z+i->pos.z+0.02); + glVertex3f(i->pos.x-s*0.025, i->pos.y+c*0.025, pos.z+i->pos.z+0.02); + glEnd(); + } + + glPopMatrix(); +} + +void Track3D::render_route(int route) +{ + prepare_render(); + + varray.apply(); + if(route>=0 && static_cast(route) builder=varray.modify(); + + base_seq.clear(); + rail_seq.clear(); + route_seq.clear(); + route_seq.resize(track.get_n_routes()); + + const Track::PartSeq &parts=track.get_parts(); + unsigned index=0; + for(Track::PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i) + build_part(*i, *builder, index); +} + +void Track3D::build_part(const Track::Part &part, GL::VertexArrayBuilder &va_builder, unsigned &base_index) +{ + static vector profile; + if(profile.empty()) + { + profile.push_back(Point(0, -0.02, 0)); + profile.push_back(Point(0, -0.014, 0.008)); + profile.push_back(Point(0, -0.014, 0.008)); + profile.push_back(Point(0, 0.014, 0.008)); + profile.push_back(Point(0, 0.014, 0.008)); + profile.push_back(Point(0, 0.02, 0)); + for(unsigned i=0; i<2; ++i) + { + profile.push_back(Point(0, -0.009+i*0.017, 0.008)); + profile.push_back(Point(0, -0.009+i*0.017, 0.0103)); + profile.push_back(Point(0, -0.009+i*0.017, 0.0103)); + profile.push_back(Point(0, -0.008+i*0.017, 0.0103)); + profile.push_back(Point(0, -0.008+i*0.017, 0.0103)); + profile.push_back(Point(0, -0.008+i*0.017, 0.008)); + } + profile.push_back(Point(0, -0.002, 0.012)); + profile.push_back(Point(0, 0.002, 0.012)); + } + static unsigned psize=profile.size(); + + const float &radius=part.radius; + const float &x=part.x; + const float &y=part.y; + const float &length=part.length; + const float &dir=part.dir; + + unsigned nsegs; + if(radius) + { + nsegs=(unsigned)(part.length*(1<=6) ? length/2 : length; + Point p(x+c*len*i-s*profile[j].y, y+s*len*i+c*profile[j].y, profile[j].z+i*track.get_slope()); + va_builder.vertex(p.x, p.y, p.z); + if(profile[j].z==0) + border.push_back(p); + } + } + } + + for(unsigned i=0; i +#include +#include "libmarklin/track.h" +#include "misc.h" + +namespace Marklin { + +class Track3D +{ +public: + Track3D(Track &, unsigned); + void set_color(const Color &c) { color=c; } + void set_quality(unsigned); + void get_bounds(float, Point &, Point &) const; + Track &get_track() const { return track; } + void render(); + void render_endpoints(); + void render_route(int); +private: + Track &track; + Color color; + std::vector border; + Msp::GL::VertexArray varray; + std::vector base_seq; + std::vector rail_seq; + std::vector > route_seq; + unsigned quality; + + void prepare_render(); + void build_object(); + void build_part(const Track::Part &, Msp::GL::VertexArrayBuilder &, unsigned &); +}; +typedef std::list Track3DSeq; + +} // namespace Marklin + +#endif diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp new file mode 100644 index 0000000..eb5a0ef --- /dev/null +++ b/source/designer/designer.cpp @@ -0,0 +1,667 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "designer.h" +#include "input.h" +#include "manipulator.h" +#include "measure.h" +#include "selection.h" + +using namespace std; +using namespace Marklin; +using namespace Msp; + +Designer::Designer(int argc, char **argv): + screen_w(1280), + screen_h(960), + input(0), + mode(SELECT), + cam_yaw(M_PI/2), + cam_pitch(-M_PI/4), + cam_pos(0, -0.5, 0.5), + shift(false), + move_x(0), + move_y(0), + zoom(0), + rotate(0), + pitch(0) +{ + cout<<"blah?\n"; + catalogue.load("tracks.dat"); + cout<second->copy(); + track->set_position(Point((n%11)*0.1-0.5, 0.2-n/11*0.3, 0)); + track->set_rotation(M_PI/2); + cat_layout->add_track(track); + } + + manipulator=new Manipulator(*this); + manipulator->signal_status.connect(sigc::mem_fun(this, &Designer::manipulation_status)); + manipulator->signal_done.connect(sigc::mem_fun(this, &Designer::manipulation_done)); + + layout=new Layout(catalogue); + layout_3d=new Layout3D(*layout); + + if(argc>1) + { + layout->load(argv[1]); + const Track3DSeq <racks=layout_3d->get_tracks(); + for(Track3DSeq::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) + { + if((*i)->get_track().get_sensor_id()) + (*i)->set_color(Color(1, 1, 0.5)); + else if((*i)->get_track().get_turnout_id()) + (*i)->set_color(Color(0.5, 1, 1)); + else if((*i)->get_track().get_flex()) + (*i)->set_color(Color(1, 0.5, 1)); + } + } + + selection=new Selection; + manipulator->set_selection(selection); + + measure=new Measure(*this); + measure->signal_changed.connect(sigc::mem_fun(this, &Designer::measure_changed)); + measure->signal_done.connect(sigc::mem_fun(this, &Designer::measure_done)); +} + +int Designer::main() +{ + setenv("__GL_SYNC_TO_VBLANK", "1", 0); + SDL_Init(SDL_INIT_VIDEO); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); + SDL_SetVideoMode(screen_w, screen_h, 32, SDL_OPENGL); + SDL_EnableUNICODE(1); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_CULL_FACE); + + font=new GL::Font(); + Parser::load(*font, "dejavu.font"); + + mode=SELECT; + + Application::main(); + + delete font; + delete input; + + SDL_Quit(); + + return exit_code; +} + +void Designer::map_pointer_coords(int x, int y, float &gx, float &gy) +{ + float cos_pitch=cos(cam_pitch); + float sin_pitch=sin(cam_pitch); + float cos_yaw=cos(cam_yaw); + float sin_yaw=sin(cam_yaw); + + float rx=sin_yaw*0.55228; + float ry=-cos_yaw*0.55228; + + float ux=cos_yaw*-sin_pitch*0.41421; + float uy=sin_yaw*-sin_pitch*0.41421; + float uz=cos_pitch*0.41421; + + float xf=(float)x*2/screen_w-1; + float yf=1-(float)y*2/screen_h; + + float vx=cos_yaw*cos_pitch + xf*rx + yf*ux; + float vy=sin_yaw*cos_pitch + xf*ry + yf*uy; + float vz=sin_pitch + yf*uz; + + gx=cam_pos.x-vx*cam_pos.z/vz; + gy=cam_pos.y-vy*cam_pos.z/vz; +} + +void Designer::tick() +{ + SDL_Event event; + while(SDL_PollEvent(&event)) + { + float gx,gy; + switch(event.type) + { + case SDL_MOUSEBUTTONDOWN: + map_pointer_coords(event.button.x, event.button.y, gx, gy); + button_press(event.button.x, screen_h-1-event.button.y, gx, gy, event.button.button); + break; + case SDL_MOUSEMOTION: + map_pointer_coords(event.motion.x, event.motion.y, gx, gy); + pointer_motion(event.motion.x, screen_h-1-event.motion.y, gx, gy); + break; + case SDL_KEYDOWN: + key_press(event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode); + break; + case SDL_KEYUP: + key_release(event.key.keysym.sym, event.key.keysym.mod); + break; + case SDL_QUIT: + exit(0); + break; + } + } + + const Time::TimeStamp t=Time::now(); + float dt=(t-last_tick)/Time::sec; + last_tick=t; + + if(move_y) + { + cam_pos.x+=cos(cam_yaw)*dt*move_y; + cam_pos.y+=sin(cam_yaw)*dt*move_y; + } + if(move_x) + { + cam_pos.x+=sin(cam_yaw)*dt*move_x; + cam_pos.y+=-cos(cam_yaw)*dt*move_x; + } + if(zoom) + { + cam_pos.x+=cos(cam_yaw)*cos(cam_pitch)*dt*zoom; + cam_pos.y+=sin(cam_yaw)*cos(cam_pitch)*dt*zoom; + cam_pos.z+=sin(cam_pitch)*dt*zoom; + } + if(rotate) + { + float vx=cos(cam_yaw)*cos(cam_pitch); + float vy=sin(cam_yaw)*cos(cam_pitch); + float vz=sin(cam_pitch); + + float gx=cam_pos.x-vx*cam_pos.z/vz; + float gy=cam_pos.y-vy*cam_pos.z/vz; + float d=sqrt(vx*vx+vy*vy)*cam_pos.z/vz; + + cam_yaw+=M_PI*dt*rotate; + if(cam_yaw>M_PI*2) + cam_yaw-=M_PI*2; + else if(cam_yaw<0) + cam_yaw+=M_PI*2; + + cam_pos.x=gx+cos(cam_yaw)*d; + cam_pos.y=gy+sin(cam_yaw)*d; + } + if(pitch) + { + cam_pitch+=M_PI/2*dt*pitch; + if(cam_pitch>M_PI/12) + cam_pitch=M_PI/12; + else if(cam_pitch<-M_PI/2) + cam_pitch=-M_PI/2; + } + + if(tooltip_timeout && t>tooltip_timeout) + { + Track3D *t3d=0; + + if(mode==CATALOGUE) + t3d=pick_track(pointer_x, pointer_y); + else + t3d=pick_track(pointer_x, pointer_y); + + if(t3d) + { + const Track &track=t3d->get_track(); + ostringstream ss; + ss.precision(2); + ss<(ss.str()); + + move_tooltip(pointer_x, pointer_y); + } + else + tooltip=L""; + + tooltip_timeout=Time::TimeStamp(); + } + + render(); + + SDL_GL_SwapBuffers(); +} + +Designer::~Designer() +{ + delete manipulator; + delete selection; + delete layout; + delete layout_3d; + delete cat_layout; + delete cat_layout_3d; + delete measure; +} + +/*** private ***/ + +void Designer::key_press(unsigned key, unsigned mod, wchar_t ch) +{ + if(mode==INPUT) + { + input->key_press(key, mod, ch); + return; + } + + if(key==SDLK_RSHIFT || key==SDLK_LSHIFT) + shift=true; + + if(key==SDLK_n) + mode=CATALOGUE; + else if(key==SDLK_g) + { + manipulator->start_move(); + mode=MANIPULATE; + } + else if(key==SDLK_r) + { + manipulator->start_rotate(); + mode=MANIPULATE; + } + else if(key==SDLK_d) + { + manipulator->duplicate(); + manipulator->start_move(); + mode=MANIPULATE; + } + else if(key==SDLK_w) + { + input=new Input(*this, "Filename"); + input->signal_cancel.connect(sigc::mem_fun(this, &Designer::input_dismiss)); + input->signal_accept.connect(sigc::mem_fun(this, &Designer::save_accept)); + mode=INPUT; + } + else if(key==SDLK_PLUS) + selection->select_more(); + else if(key==SDLK_l && (mod&KMOD_SHIFT)) + { + const TrackSeq &tracks=layout->get_tracks(); + float len=0; + for(TrackSeq::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + len+=(*i)->get_total_length(); + cout<<"Total length: "<select_linked(); + else if(key==SDLK_m) + { + measure->start(); + mode=MEASURE; + } + else if(key==SDLK_z) + { + manipulator->start_elevate(); + mode=MANIPULATE; + } + else if(key==SDLK_ESCAPE) + { + if(mode==MANIPULATE) + manipulator->cancel(); + else if(mode==CATALOGUE) + mode=SELECT; + else + selection->clear(); + } + else if(key==SDLK_x) + { + Selection::TrackSet tracks=selection->get_tracks(); + selection->clear(); + for(Selection::TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + layout->remove_track(*i); + delete *i; + } + } + else if(key==SDLK_f && (mod&KMOD_SHIFT)) + { + const Selection::TrackSet &tracks=selection->get_tracks(); + const TrackSeq <racks=layout->get_tracks(); + for(Selection::TrackSet::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + (*i)->set_flex(!(*i)->get_flex()); + (*i)->break_links(); + for(TrackSeq::const_iterator j=ltracks.begin(); j!=ltracks.end(); ++j) + if(*j!=*i) + (*i)->snap_to(**j, true); + + Track3D *t3d=layout_3d->get_track(*i); + if((*i)->get_flex()) + t3d->set_color(Color(1, 0.5, 1)); + else + t3d->set_color(Color(1, 1, 1)); + } + } + else if(key==SDLK_f) + manipulator->flatten(); + else if(key==SDLK_e && (mod&KMOD_SHIFT)) + manipulator->even_slope(true); + else if(key==SDLK_e) + manipulator->even_slope(); + else if(key==SDLK_t) + { + Track *track=selection->get_track(); + if(selection->size()==1 && track->get_n_routes()>1) + { + ostringstream ss; + ss<get_turnout_id(); + input=new Input(*this, "Turnout ID", ss.str()); + input->signal_cancel.connect(sigc::mem_fun(this, &Designer::input_dismiss)); + input->signal_accept.connect(sigc::mem_fun(this, &Designer::turnout_id_accept)); + mode=INPUT; + } + } + else if(key==SDLK_s) + { + Track *track=selection->get_track(); + if(selection->size()==1 && track->get_n_routes()==1) + { + ostringstream ss; + ss<get_sensor_id(); + input=new Input(*this, "Sensor ID", ss.str()); + input->signal_cancel.connect(sigc::mem_fun(this, &Designer::input_dismiss)); + input->signal_accept.connect(sigc::mem_fun(this, &Designer::sensor_id_accept)); + mode=INPUT; + } + } + else if(key==SDLK_RIGHT) + rotate=-1; + else if(key==SDLK_LEFT) + rotate=1; + else if(key==SDLK_UP) + move_y=1; + else if(key==SDLK_DOWN) + move_y=-1; + else if(key==SDLK_INSERT) + zoom=-1; + else if(key==SDLK_PAGEUP) + zoom=1; + else if(key==SDLK_HOME) + pitch=1; + else if(key==SDLK_END) + pitch=-1; + else if(key==SDLK_DELETE) + move_x=-1; + else if(key==SDLK_PAGEDOWN) + move_x=1; +} + +void Designer::key_release(unsigned key, unsigned) +{ + if(mode==INPUT) + return; + + if(key==SDLK_RSHIFT || key==SDLK_LSHIFT) + shift=false; + else if(key==SDLK_RIGHT || key==SDLK_LEFT) + rotate=0; + else if(key==SDLK_UP || key==SDLK_DOWN) + move_y=0; + else if(key==SDLK_INSERT || key==SDLK_PAGEUP) + zoom=0; + else if(key==SDLK_HOME || key==SDLK_END) + pitch=0; + else if(key==SDLK_DELETE || key==SDLK_PAGEDOWN) + move_x=0; +} + +void Designer::button_press(int x, int y, float gx, float gy, unsigned btn) +{ + if(mode==CATALOGUE) + { + if(btn==1) + { + Track3D *ctrack=pick_track(x, y); + if(ctrack) + { + Track *track=ctrack->get_track().copy(); + track->set_position(Point(gx, gy, 0)); + layout->add_track(track); + + selection->clear(); + selection->add_track(track); + + mode=SELECT; + } + } + else + mode=SELECT; + } + else if(mode==SELECT) + { + if(btn==1) + { + Track3D *track=pick_track(x, y); + if(track) + { + if(!shift) + selection->clear(); + selection->toggle_track(&track->get_track()); + } + } + } + else if(mode==MANIPULATE) + manipulator->button_press(x, y, gx, gy, btn); + else if(mode==MEASURE) + measure->button_press(x, y, gx, gy, btn); +} + +void Designer::pointer_motion(int x, int y, float gx, float gy) +{ + if(mode==SELECT || mode==CATALOGUE) + { + pointer_x=x; + pointer_y=y; + tooltip_timeout=Time::now()+100*Time::msec; + } + + if(mode!=INPUT) + { + manipulator->pointer_motion(x, y, gx, gy); + measure->pointer_motion(x, y, gx, gy); + } + + if(mode==MEASURE || mode==MANIPULATE) + move_tooltip(x, y); +} + +void Designer::project_3d() +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-0.055228, 0.055228, -0.041421, 0.041421, 0.1, 10); + glMatrixMode(GL_MODELVIEW); +} + +void Designer::apply_camera() +{ + glLoadIdentity(); + if(mode==CATALOGUE) + glTranslatef(0, 0, -1); + else + { + glRotatef(-cam_pitch*180/M_PI-90, 1, 0, 0); + glRotatef(90-cam_yaw*180/M_PI, 0, 0, 1); + glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); + } +} + +void Designer::render() +{ + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + + project_3d(); + apply_camera(); + if(mode==CATALOGUE) + cat_layout_3d->render(); + else + { + layout_3d->render(true); + manipulator->render(); + if(mode==MEASURE) + measure->render(); + } + + /*glBegin(GL_LINES); + glColor4f(1, 0, 0, 1); + glVertex3f(0, 0, 0); + glVertex3f(0.5, 0, 0); + glColor4f(0, 1, 0, 1); + glVertex3f(0, 0, 0); + glVertex3f(0, 0.5, 0); + glColor4f(0, 0, 1, 1); + glVertex3f(0, 0, 0); + glVertex3f(0, 0, 0.5); + glEnd();*/ + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, screen_w, 0, screen_h, 0, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_DEPTH_TEST); + + if(!tooltip.empty()) + { + glTranslatef(tooltip_x, tooltip_y, 0); + glScalef(20, 20, 20); + float width=font->get_string_width(tooltip); + glColor4f(0, 0, 0, 0.5); + glBegin(GL_QUADS); + glVertex2f(0, 0); + glVertex2f(width, 0); + glVertex2f(width, 1); + glVertex2f(0, 1); + glEnd(); + glColor4f(1, 1, 1, 1); + font->draw_string(tooltip); + } + + if(mode==INPUT) + input->render(); +} + +Track3D *Designer::pick_track(int x, int y) +{ + Layout3D *l=layout_3d; + if(mode==CATALOGUE) + l=cat_layout_3d; + + float xx=((float)(x-(int)screen_w/2)/screen_h)*0.82843; + float yy=((float)y/screen_h-0.5)*0.82843; + float size=(float)4/screen_h*0.82843; + + project_3d(); + apply_camera(); + + return l->pick_track(xx, yy, size); +} + +void Designer::manipulation_status(const string &status) +{ + tooltip=decode(status); +} + +void Designer::manipulation_done(bool) +{ + mode=SELECT; +} + +void Designer::measure_changed() +{ + float pard=measure->get_parallel_distance()*1000; + float perpd=measure->get_perpendicular_distance()*1000; + float d=sqrt(pard*pard+perpd*perpd); + float adiff=measure->get_angle_difference()*180/M_PI; + ostringstream ss; + ss.precision(3); + ss<<"Par "<(ss.str()); +} + +void Designer::measure_done() +{ + mode=SELECT; +} + +void Designer::move_tooltip(int x, int y) +{ + int w=(int)(font->get_string_width(tooltip)*20); + tooltip_x=max(min((int)screen_w-w, x), 0); + tooltip_y=max(min((int)screen_h-20, y), 0); +} + +void Designer::save_accept() +{ + layout->save(input->get_text()); + + input_dismiss(); +} + +void Designer::turnout_id_accept() +{ + Track *track=selection->get_track(); + unsigned id=lexical_cast(input->get_text()); + track->set_turnout_id(id); + + Track3D *t3d=layout_3d->get_track(track); + if(id) + t3d->set_color(Color(0.5, 1, 1)); + else + t3d->set_color(Color(1, 1, 1)); + + input_dismiss(); +} + +void Designer::sensor_id_accept() +{ + Track *track=selection->get_track(); + unsigned id=lexical_cast(input->get_text()); + track->set_sensor_id(id); + + Track3D *t3d=layout_3d->get_track(track); + if(id) + t3d->set_color(Color(1, 1, 0.5)); + else + t3d->set_color(Color(1, 1, 1)); + + input_dismiss(); +} + +void Designer::input_dismiss() +{ + delete input; + input=0; + mode=SELECT; +} + +Application::RegApp Designer::reg; diff --git a/source/designer/designer.h b/source/designer/designer.h new file mode 100644 index 0000000..ece41a5 --- /dev/null +++ b/source/designer/designer.h @@ -0,0 +1,90 @@ +#ifndef DESIGNER_H_ +#define DESIGNER_H_ + +#include +#include +#include +#include +#include "libmarklin/catalogue.h" +#include "libmarklin/layout.h" +#include "3d/layout.h" +#include "3d/track.h" + +class Input; +class Manipulator; +class Measure; +class Selection; + +class Designer: public Msp::Application +{ +public: + Designer(int, char **); + Marklin::Layout *get_layout() { return layout; } + Marklin::Layout3D *get_layout_3d() { return layout_3d; } + Msp::GL::Font &get_font() { return *font; } + int main(); + void map_pointer_coords(int, int, float &, float &); + ~Designer(); +private: + enum Mode + { + SELECT, + CATALOGUE, + MANIPULATE, + MEASURE, + INPUT + }; + + unsigned screen_w; + unsigned screen_h; + Msp::GL::Font *font; + Marklin::Catalogue catalogue; + Marklin::Layout *layout; + Marklin::Layout3D *layout_3d; + Marklin::Layout *cat_layout; + Marklin::Layout3D *cat_layout_3d; + Selection *selection; + Manipulator *manipulator; + Measure *measure; + Input *input; + Mode mode; + float cam_yaw; + float cam_pitch; + Marklin::Point cam_pos; + bool shift; + int move_x; + int move_y; + int zoom; + int rotate; + int pitch; + int pointer_x; + int pointer_y; + int tooltip_x; + int tooltip_y; + std::wstring tooltip; + Msp::Time::TimeStamp tooltip_timeout; + Msp::Time::TimeStamp last_tick; + + void tick(); + void key_press(unsigned, unsigned, wchar_t); + void key_release(unsigned, unsigned); + void button_press(int, int, float, float, unsigned); + void pointer_motion(int, int, float, float); + void project_3d(); + void apply_camera(); + void render(); + Marklin::Track3D *pick_track(int, int); + void manipulation_status(const std::string &); + void manipulation_done(bool); + void measure_changed(); + void measure_done(); + void move_tooltip(int, int); + void save_accept(); + void turnout_id_accept(); + void sensor_id_accept(); + void input_dismiss(); + + static Msp::Application::RegApp reg; +}; + +#endif diff --git a/source/designer/input.cpp b/source/designer/input.cpp new file mode 100644 index 0000000..1b18646 --- /dev/null +++ b/source/designer/input.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include "designer.h" +#include "input.h" + +using namespace std; +using namespace Msp; + +Input::Input(Designer &d, const string &t, const string &e): + designer(d), + title(t), + text(e), + pos(text.size()) +{ } + +void Input::key_press(unsigned key, unsigned, wchar_t ch) +{ + if(key==SDLK_RETURN) + signal_accept.emit(); + else if(key==SDLK_ESCAPE) + signal_cancel.emit(); + else if(key==SDLK_BACKSPACE) + { + if(pos>0) + { + text.erase(pos-1, 1); + --pos; + } + } + else if(key==SDLK_DELETE) + { + if(pos0) + --pos; + } + else if(key==SDLK_RIGHT) + { + if(pos=0x20) + { + text.insert(pos, 1, ch); + ++pos; + } +} + +void Input::render() +{ + glLoadIdentity(); + glTranslatef(300, 450, 0); + + GL::Texture::unbind(); + glColor4f(0.7, 0.7, 0.7, 0.9); + glBegin(GL_QUADS); + glVertex2f(0, 0); + glVertex2f(680, 0); + glVertex2f(680, 60); + glVertex2f(0, 60); + glEnd(); + + glColor4f(0, 0, 0, 1); + glTranslatef(5, 35, 0); + + glPushMatrix(); + glScalef(20, 20, 20); + designer.get_font().draw_string(title); + glPopMatrix(); + + glTranslatef(0, -30, 0); + glPushMatrix(); + glScalef(20, 20, 20); + designer.get_font().draw_string(text); + + glTranslatef(designer.get_font().get_string_width(text.substr(0, pos)), 0, 0); + glDisable(GL_TEXTURE_2D); + glBegin(GL_LINES); + glVertex2f(0, 0); + glVertex2f(0, 1); + glEnd(); + glPopMatrix(); +} diff --git a/source/designer/input.h b/source/designer/input.h new file mode 100644 index 0000000..276ce5f --- /dev/null +++ b/source/designer/input.h @@ -0,0 +1,26 @@ +#ifndef INPUT_H_ +#define INPUT_H_ + +#include +#include + +class Designer; + +class Input +{ +public: + sigc::signal signal_accept; + sigc::signal signal_cancel; + + Input(Designer &, const std::string &, const std::string & =""); + const std::string &get_text() { return text; } + void key_press(unsigned, unsigned, wchar_t); + void render(); +private: + Designer &designer; + std::string title; + std::string text; + unsigned pos; +}; + +#endif diff --git a/source/designer/manipulator.cpp b/source/designer/manipulator.cpp new file mode 100644 index 0000000..cbeb982 --- /dev/null +++ b/source/designer/manipulator.cpp @@ -0,0 +1,479 @@ +#include +#include +#include +#include "3d/layout.h" +#include "designer.h" +#include "manipulator.h" +#include "selection.h" + +using namespace std; +using namespace Marklin; +using namespace Msp; + +#include + +Manipulator::Manipulator(Designer &d): + designer(d), + selection(0), + wrap_rot(0), + mode(NONE), + angle(0) +{ } + +void Manipulator::set_selection(Selection *s) +{ + selection_changed_conn.disconnect(); + + selection=s; + if(selection) + selection_changed_conn=selection->signal_changed.connect(sigc::mem_fun(this, &Manipulator::selection_changed)); + + selection_changed(); +} + +void Manipulator::start_move() +{ + if(mode) + cancel(); + + move_origin=gpointer; + + mode=MOVE; +} + +void Manipulator::start_rotate() +{ + if(mode) + cancel(); + + rot_origin=atan2(gpointer.y-center.y, gpointer.x-center.x); + + mode=ROTATE; +} + +void Manipulator::start_elevate() +{ + if(mode) + cancel(); + + elev_origin=pointer_y; + + mode=ELEVATE; +} + +void Manipulator::duplicate() +{ + if(mode) + cancel(); + + TrackSeq new_tracks; + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + Track *track=i->track->copy(); + designer.get_layout()->add_track(track); + new_tracks.push_back(track); + } + + selection->clear(); + for(TrackSeq::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i) + { + selection->add_track(*i); + for(TrackSeq::iterator j=i; j!=new_tracks.end(); ++j) + if(j!=i) + (*i)->snap_to(**j, true); + } +} + +void Manipulator::flatten() +{ + if(mode) + cancel(); + + if(tracks.empty()) return; + + float z=0; + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + z+=i->track->get_position().z+i->track->get_slope()/2; + z/=tracks.size(); + + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + Point p=i->track->get_position(); + i->track->set_position(Point(p.x, p.y, z)); + i->track->set_slope(0); + } + + for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) + (*i)->check_slope(); + + update_wrap(); +} + +void Manipulator::even_slope(bool smooth) +{ + if(mode) + cancel(); + + if(neighbors.size()!=2) + return; + + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + if(i->track->get_endpoints().size()!=2) + return; + + TrackSeq tracks2; + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + tracks2.push_back(i->track); + + float total_len=0; + + TrackOrderSeq order; + Track *cur=neighbors.front(); + while(tracks2.size()) + { + bool rev=false; + for(TrackSeq::iterator i=tracks2.begin(); i!=tracks2.end(); ++i) + { + const Track::EndpointSeq &epl=(*i)->get_endpoints(); + if(epl.front().link==cur) + { + cur=*i; + tracks2.erase(i); + break; + } + else if(epl.back().link==cur) + { + cur=*i; + rev=true; + tracks2.erase(i); + break; + } + } + order.push_back(TrackOrder(cur, rev)); + total_len+=cur->get_length(); + } + + const Track::Endpoint *ep=neighbors.front()->get_endpoint_by_link(order.front().track); + float start_z=neighbors.front()->get_position().z+ep->pos.z; + ep=neighbors.back()->get_endpoint_by_link(order.back().track); + float end_z=neighbors.back()->get_position().z+ep->pos.z; + + if(smooth) + { + float dir=(end_z>start_z)?1:-1; + float cur_slope=0; + while((end_z-start_z)*dir/total_len>cur_slope+0.025 && order.size()>2) + { + cur_slope+=0.025; + + float dz=order.front().track->get_length()*dir*cur_slope; + set_slope(order.front(), start_z, dz); + start_z+=dz; + total_len-=order.front().track->get_length(); + order.erase(order.begin()); + + dz=order.back().track->get_length()*dir*cur_slope; + set_slope(order.back(), end_z-dz, dz); + end_z-=dz; + total_len-=order.back().track->get_length(); + order.erase(--order.end()); + } + } + + float cur_z=start_z; + for(TrackOrderSeq::iterator i=order.begin(); i!=order.end(); ++i) + { + float dz=i->track->get_length()*(end_z-start_z)/total_len; + set_slope(*i, cur_z, dz); + cur_z+=dz; + } + + for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) + (*i)->check_slope(); + + update_wrap(); +} + +void Manipulator::cancel() +{ + if(!mode) + return; + mode=NONE; + + wrap_pos=center; + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + i->track->set_position(Point(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z)); + i->track->set_rotation(i->rot); + } + + for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) + (*i)->check_slope(); + + angle=0; + //snapped=0; + + signal_done.emit(false); +} + +void Manipulator::button_press(int, int, float, float, unsigned btn) +{ + if(btn==3) + cancel(); + else if(mode) + { + mode=NONE; + update_wrap(); + //snapped=0; + + for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) + for(MTrackSeq::iterator j=tracks.begin(); j!=tracks.end(); ++j) + j->track->break_link(**i); + + const TrackSeq <racks=designer.get_layout()->get_tracks(); + for(TrackSeq::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) + { + bool ok=true; + for(MTrackSeq::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j) + ok=(j->track!=*i); + if(!ok) continue; + + for(MTrackSeq::iterator j=tracks.begin(); j!=tracks.end(); ++j) + j->track->snap_to(**i, true); + } + + update_neighbors(); + + signal_done.emit(true); + } +} + +void Manipulator::pointer_motion(int, int y, float gx, float gy) +{ + pointer_y=y; + gpointer=Point(gx, gy, 0); + + if(mode==MOVE) + { + Point delta(gpointer.x-move_origin.x, gpointer.y-move_origin.y, 0); + + wrap_pos=Point(center.x+delta.x, center.y+delta.y, center.z); + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + i->track->set_position(Point(wrap_pos.x+i->pos.x, wrap_pos.y+i->pos.y, wrap_pos.z+i->pos.z)); + i->track->set_rotation(i->rot); + } + + const TrackSeq <racks=designer.get_layout()->get_tracks(); + MTrack *snapped=0; + for(TrackSeq::const_iterator i=ltracks.begin(); (i!=ltracks.end() && !snapped); ++i) + { + bool ok=true; + for(MTrackSeq::iterator j=tracks.begin(); (j!=tracks.end() && ok); ++j) + ok=(j->track!=*i); + if(!ok) continue; + + for(MTrackSeq::iterator j=tracks.begin(); (j!=tracks.end() && !snapped); ++j) + if(j->track->snap_to(**i, false)) + snapped=&*j; + } + + if(snapped) + { + float da=snapped->track->get_rotation()-snapped->rot; + float c=cos(da); + float s=sin(da); + const Point &sp=snapped->track->get_position(); + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + if(&*i==snapped) + continue; + + Point dp(i->pos.x-snapped->pos.x, i->pos.y-snapped->pos.y, 0); + i->track->set_position(Point(sp.x+c*dp.x-s*dp.y, sp.y+s*dp.x+c*dp.y, sp.z)); + i->track->set_rotation(i->rot+da); + } + } + } + else if(mode==ROTATE) + { + float a=atan2(gpointer.y-center.y, gpointer.x-center.x); + angle+=a-rot_origin; + rot_origin=a; + + wrap_rot=angle; + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + float c=cos(angle); + float s=sin(angle); + i->track->set_position(Point(center.x+c*i->pos.x-s*i->pos.y, center.y+s*i->pos.x+c*i->pos.y, center.z*i->pos.z)); + i->track->set_rotation(angle+i->rot); + } + } + else if(mode==ELEVATE) + { + float dz=(y-elev_origin)/1000.; + + ostringstream ss; + ss.precision(3); + ss<<"Elevation: "<track->set_position(Point(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z+dz)); + + for(TrackSeq::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) + (*i)->check_slope(); + } +} + +void Manipulator::render() +{ + glPushMatrix(); + glTranslatef(wrap_pos.x, wrap_pos.y, wrap_pos.z); + glRotatef(wrap_rot*180/M_PI, 0, 0, 1); + + glLineWidth(2); + glColor4f(0, 1, 0, 0.5); + for(list::iterator i=wrap.begin(); i!=wrap.end(); ++i) + { + glPushMatrix(); + glTranslatef(i->pos.x, i->pos.y, i->pos.z); + glRotatef(i->rot*180/M_PI, 0, 0, 1); + + glBegin(GL_LINE_LOOP); + glVertex2f(-i->width/2, -i->height/2); + glVertex2f(i->width/2, -i->height/2); + glVertex2f(i->width/2, i->height/2); + glVertex2f(-i->width/2, i->height/2); + glEnd(); + + glPopMatrix(); + } + + glPopMatrix(); +} + +/*** private ***/ + +void Manipulator::selection_changed() +{ + if(mode) + cancel(); + + tracks.clear(); + if(selection) + { + const Selection::TrackSet &stracks=selection->get_tracks(); + tracks.insert(tracks.end(), stracks.begin(), stracks.end()); + } + + update_neighbors(); + update_wrap(); +} + +void Manipulator::update_wrap() +{ + wrap.clear(); + float min_x=0,max_x=0; + float min_y=0,max_y=0; + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + Track3D *t3d=designer.get_layout_3d()->get_track(i->track); + + TrackWrap tw; + float min_area=100; + for(float a=0; aget_bounds(a, minp, maxp); + float area=(maxp.x-minp.x)*(maxp.y-minp.y); + if(areatrack->get_position(); + i->pos=Point(tp.x-center.x, tp.y-center.y, tp.z); + } + for(list::iterator i=wrap.begin(); i!=wrap.end(); ++i) + { + i->pos.x-=center.x; + i->pos.y-=center.y; + } +} + +void Manipulator::update_neighbors() +{ + neighbors.clear(); + for(MTrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + const Track::EndpointSeq &epl=i->track->get_endpoints(); + for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j) + { + if(!j->link) + continue; + if(find(neighbors.begin(), neighbors.end(), j->link)!=neighbors.end()) + continue; + + bool ok=true; + for(MTrackSeq::iterator k=tracks.begin(); (k!=tracks.end() && ok); ++k) + ok=(k->track!=j->link); + + if(ok) + neighbors.push_back(j->link); + } + } +} + +void Manipulator::set_slope(TrackOrder &track, float z, float dz) +{ + const Point &p=track.track->get_position(); + if(track.rev) + { + track.track->set_position(Point(p.x, p.y, z+dz)); + track.track->set_slope(-dz); + } + else + { + track.track->set_position(Point(p.x, p.y, z)); + track.track->set_slope(dz); + } +} + +Manipulator::MTrack::MTrack(Track *t): + track(t), + pos(track->get_position()), + rot(track->get_rotation()) +{ } diff --git a/source/designer/manipulator.h b/source/designer/manipulator.h new file mode 100644 index 0000000..3a8882e --- /dev/null +++ b/source/designer/manipulator.h @@ -0,0 +1,89 @@ +#ifndef MANIPULATOR_H_ +#define MANIPULATOR_H_ + +#include +#include "3d/track.h" + +class Designer; +class Selection; + +class Manipulator +{ +public: + sigc::signal signal_status; + sigc::signal signal_done; + + Manipulator(Designer &); + void set_selection(Selection *); + void start_move(); + void start_rotate(); + void start_elevate(); + void duplicate(); + void flatten(); + void even_slope(bool =false); + void cancel(); + void button_press(int, int, float, float, unsigned); + void pointer_motion(int, int, float, float); + void render(); +private: + enum Mode + { + NONE, + MOVE, + ROTATE, + ELEVATE + }; + + struct MTrack + { + Marklin::Track *track; + Marklin::Point pos; + float rot; + + MTrack(Marklin::Track *); + }; + typedef std::list MTrackSeq; + + struct TrackOrder + { + Marklin::Track *track; + bool rev; + + TrackOrder(Marklin::Track *t, bool r): track(t), rev(r) { } + }; + typedef std::list TrackOrderSeq; + + struct TrackWrap + { + Marklin::Point pos; + float rot; + float width; + float height; + }; + + Designer &designer; + Selection *selection; + MTrackSeq tracks; + Marklin::Point center; + + std::list wrap; + Marklin::Point wrap_pos; + float wrap_rot; + + Marklin::Point gpointer; + int pointer_y; + Mode mode; + Marklin::Point move_origin; + float angle; + float rot_origin; + int elev_origin; + Marklin::TrackSeq neighbors; + sigc::connection selection_changed_conn; + + void selection_changed(); + void update_wrap(); + void update_neighbors(); + void set_slope(TrackOrder &, float, float); +}; + +#endif diff --git a/source/designer/measure.cpp b/source/designer/measure.cpp new file mode 100644 index 0000000..6f1d7bc --- /dev/null +++ b/source/designer/measure.cpp @@ -0,0 +1,120 @@ +#include +#include +#include "designer.h" +#include "3d/layout.h" +#include "measure.h" + +using namespace Marklin; +using namespace Msp; + +Measure::Measure(Designer &d): + designer(d), + state(NONE) +{ } + +void Measure::start() +{ + state=STARTING; +} + +void Measure::snap_to_tracks(Point &pt, float &dir) +{ + const TrackSeq <racks=designer.get_layout()->get_tracks(); + for(TrackSeq::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) + if((*i)->snap(pt, dir)) + return; +} + +void Measure::button_press(int, int, float gx, float gy, unsigned btn) +{ + if(!state) + return; + + if(btn==1) + { + spoint=Point(gx, gy, 0); + sdir=0; + snap_to_tracks(spoint, sdir); + + state=ACTIVE; + } + else if(btn==3) + { + if(state==ACTIVE) + state=STARTING; + else + { + state=NONE; + signal_done.emit(); + } + } +} + +void Measure::pointer_motion(int, int, float gx, float gy) +{ + if(!state) + return; + + pointer=Point(gx, gy, 0); + float dir=sdir; + snap_to_tracks(pointer, dir); + + if(state!=STARTING) + { + Point delta(pointer.x-spoint.x, pointer.y-spoint.y, 0); + float c=cos(sdir); + float s=sin(sdir); + + par_dist=delta.x*c+delta.y*s; + perp_dist=delta.x*s-delta.y*c; + + adiff=dir-sdir+M_PI; + while(adiff<-M_PI) + adiff+=M_PI*2; + while(adiff>M_PI) + adiff-=M_PI*2; + + signal_changed.emit(); + } +} + +void Measure::render() +{ + glPushMatrix(); + if(state==ACTIVE) + glTranslatef(spoint.x, spoint.y, spoint.z); + else if(state==STARTING) + glTranslatef(pointer.x, pointer.y, pointer.z); + + glDisable(GL_CULL_FACE); + glColor4f(1, 1, 1, 1); + glBegin(GL_QUAD_STRIP); + for(unsigned i=0; i<=16; ++i) + { + float x=cos(i*M_PI/8)*0.005; + float y=sin(i*M_PI/8)*0.005; + glVertex3f(x, y, 0); + glVertex3f(x, y, 0.01); + } + glEnd(); + + if(state==ACTIVE) + { + float c=cos(sdir); + float s=sin(sdir); + glBegin(GL_QUAD_STRIP); + glVertex3f(0, 0, 0); + glVertex3f(0, 0, 0.01); + glVertex3f(c*par_dist, s*par_dist, 0); + glVertex3f(c*par_dist, s*par_dist, 0.01); + glVertex3f(pointer.x-spoint.x, pointer.y-spoint.y, 0); + glVertex3f(pointer.x-spoint.x, pointer.y-spoint.y, 0.01); + /*glVertex3f(s*perp_dist, -c*perp_dist, 0); + glVertex3f(s*perp_dist, -c*perp_dist, 0.01);*/ + glVertex3f(0, 0, 0); + glVertex3f(0, 0, 0.01); + glEnd(); + } + + glPopMatrix(); +} diff --git a/source/designer/measure.h b/source/designer/measure.h new file mode 100644 index 0000000..d7c7b77 --- /dev/null +++ b/source/designer/measure.h @@ -0,0 +1,42 @@ +#ifndef MEASURE_H_ +#define MEASURE_H_ + +#include + +class Designer; + +class Measure +{ +public: + sigc::signal signal_done; + sigc::signal signal_changed; + + Measure(Designer &); + float get_parallel_distance() const { return par_dist; } + float get_perpendicular_distance() const { return perp_dist; } + float get_angle_difference() const { return adiff; } + void start(); + void button_press(int, int, float, float, unsigned); + void pointer_motion(int, int, float, float); + void render(); +private: + enum State + { + NONE, + STARTING, + ACTIVE + }; + + Designer &designer; + Marklin::Point pointer; + Marklin::Point spoint; + float sdir; + float par_dist; + float perp_dist; + float adiff; + State state; + + void snap_to_tracks(Marklin::Point &, float &); +}; + +#endif diff --git a/source/designer/selection.cpp b/source/designer/selection.cpp new file mode 100644 index 0000000..a693c0a --- /dev/null +++ b/source/designer/selection.cpp @@ -0,0 +1,89 @@ +#include +#include "selection.h" + +using namespace std; +using namespace Marklin; +using namespace Msp; + +Track *Selection::get_track() const +{ + if(tracks.empty()) + return 0; + else + return *tracks.begin(); +} + +void Selection::clear() +{ + tracks.clear(); + signal_changed.emit(); +} + +void Selection::add_track(Track *t) +{ + if(tracks.insert(t).second) + signal_changed.emit(); +} + +void Selection::remove_track(Track *t) +{ + if(tracks.erase(t)) + signal_changed.emit(); +} + +void Selection::toggle_track(Track *t) +{ + if(!tracks.erase(t)) + tracks.insert(t); + + signal_changed.emit(); +} + +void Selection::select_more() +{ + TrackSet new_tracks; + for(TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + const Track::EndpointSeq &epl=(*i)->get_endpoints(); + for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j) + if(j->link) + new_tracks.insert(j->link); + } + + bool changed=false; + for(TrackSet::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i) + if(tracks.insert(*i).second) + changed=true; + + if(changed) + signal_changed.emit(); +} + +void Selection::select_linked() +{ + bool changed=false; + TrackSeq queue(tracks.begin(), tracks.end()); + while(!queue.empty()) + { + Track *track=queue.front(); + queue.erase(queue.begin()); + + const Track::EndpointSeq &epl=track->get_endpoints(); + for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j) + if(j->link && tracks.insert(j->link).second) + { + queue.push_back(j->link); + changed=true; + } + } + for(TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + const Track::EndpointSeq &epl=(*i)->get_endpoints(); + for(Track::EndpointSeq::const_iterator j=epl.begin(); j!=epl.end(); ++j) + if(j->link && tracks.insert(j->link).second) + changed=true; + } + + if(changed) + signal_changed.emit(); +} diff --git a/source/designer/selection.h b/source/designer/selection.h new file mode 100644 index 0000000..36e4435 --- /dev/null +++ b/source/designer/selection.h @@ -0,0 +1,28 @@ +#ifndef SELECTION_H_ +#define SELECTION_H_ + +#include +#include +#include "3d/track.h" + +class Selection +{ +public: + typedef std::set TrackSet; + + sigc::signal signal_changed; + + const TrackSet &get_tracks() const { return tracks; } + Marklin::Track *get_track() const; + unsigned size() const { return tracks.size(); } + void clear(); + void add_track(Marklin::Track *); + void remove_track(Marklin::Track *); + void toggle_track(Marklin::Track *); + void select_more(); + void select_linked(); +private: + TrackSet tracks; +}; + +#endif diff --git a/source/engineer/engineer.cpp b/source/engineer/engineer.cpp new file mode 100644 index 0000000..573ef6f --- /dev/null +++ b/source/engineer/engineer.cpp @@ -0,0 +1,485 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "engineer.h" +#include "mainpanel.h" +#include "trainpanel.h" + +using namespace std; +using namespace Marklin; +using namespace Msp; + +#include + +Engineer::Engineer(int argc, char **argv): + screen_w(1280), + screen_h(960), + fullscreen(false), + layout(catalogue), + layout_3d(layout), + no_lighting(false), + placing_train(0) +{ + string res; + bool debug=false; + string device="/dev/ttyS0"; + unsigned quality=4; + + GetOpt getopt; + getopt.add_option('r', "resolution", res, GetOpt::REQUIRED_ARG); + getopt.add_option('f', "fullscreen", fullscreen, GetOpt::NO_ARG); + getopt.add_option('g', "debug", debug, GetOpt::NO_ARG); + getopt.add_option('d', "device", device, GetOpt::REQUIRED_ARG); + getopt.add_option('q', "quality", quality, GetOpt::REQUIRED_ARG); + getopt.add_option( "no-lighting", no_lighting, GetOpt::NO_ARG); + getopt(argc, argv); + + if(!res.empty()) + { + if(RegMatch m=Regex("([1-9][0-9]*)x([1-9][0-9]*)").match(res)) + { + screen_w=lexical_cast(m[1].str); + screen_h=lexical_cast(m[2].str); + } + else + throw UsageError("Invalid resolution"); + } + + if(device!="none") + control.open(device); + + control.set_debug(debug); + + layout_3d.set_quality(quality); + + catalogue.load("tracks.dat"); + + const list &args=getopt.get_args(); + if(args.empty()) + throw UsageError("No layout given"); + layout.load(args.front()); + + trfc_mgr=new TrafficManager(control, layout); + + view_all(); + + /*const TrackSeq &tracks=layout.get_tracks(); + + for(TrackSeq::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + if(unsigned trnt_id=(*i)->get_turnout_id()) + { + Turnout *trnt=new Turnout(control, trnt_id); + trnt->signal_route_changed.connect(sigc::mem_fun(this, &Engineer::turnout_route_changed)); + } + if(unsigned sens_id=(*i)->get_sensor_id()) + { + Sensor *sens=new Sensor(control, sens_id); + sens->signal_state_changed.connect(sigc::bind(sigc::mem_fun(this, &Engineer::sensor_state_changed), sens_id)); + } + }*/ +} + +Engineer::~Engineer() +{ +} + +void Engineer::add_train(unsigned addr) +{ + if(control.get_locomotive(addr)) + return; + + Locomotive *loco=new Locomotive(control, addr); + Train *train=new Train(*trfc_mgr, *loco); + + TrainPanel *tpanel=new TrainPanel(*this, ui_res, *train); + int y=main_panel->get_geometry().y; + for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i) + y-=(*i)->get_geometry().h; + tpanel->set_position(0, y-tpanel->get_geometry().h); + train_panels.push_back(tpanel); + + placing_train=train; +} + +int Engineer::main() +{ + SDL_Init(SDL_INIT_VIDEO); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); + SDL_Surface *screen=SDL_SetVideoMode(screen_w, screen_h, 32, SDL_OPENGL|(fullscreen?SDL_FULLSCREEN:0)); + if(!screen) + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + screen=SDL_SetVideoMode(screen_w, screen_h, 32, SDL_OPENGL|(fullscreen?SDL_FULLSCREEN:0)); + } + if(!screen) + { + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0); + screen=SDL_SetVideoMode(screen_w, screen_h, 32, SDL_OPENGL|(fullscreen?SDL_FULLSCREEN:0)); + } + if(!screen) + throw Exception("Couldn't create window"); + + glEnableClientState(GL_VERTEX_ARRAY); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + glDepthFunc(GL_LEQUAL); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + font=new GL::Font(); + if(screen_w>=1024) + { + font_size=20; + Parser::load(*font, "dejavu-20.font"); + } + else + { + font_size=12; + Parser::load(*font, "dejavu-12.font"); + } + + Parser::load(ui_res, "engineer.res"); + main_panel=new MainPanel(*this, ui_res); + main_panel->set_position(0, screen_h-main_panel->get_geometry().h); + + Application::main(); + + delete font; + delete main_panel; + + SDL_Quit(); + + return exit_code; +} + +void Engineer::tick() +{ + //cout<<"tick\n"; + + SDL_Event event; + while(SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_MOUSEBUTTONDOWN: + button_press(event.button.x, screen_h-1-event.button.y, event.button.button); + break; + case SDL_MOUSEBUTTONUP: + button_release(event.button.x, screen_h-1-event.button.y, event.button.button); + break; + case SDL_MOUSEMOTION: + pointer_motion(event.motion.x, screen_h-1-event.motion.y); + break; + case SDL_KEYDOWN: + key_press(event.key.keysym.sym, event.key.keysym.mod); + break; + case SDL_QUIT: + exit(0); + break; + } + } + + control.tick(); + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + project_3d(); + glLoadIdentity(); + glRotatef(-cam_rot*180/M_PI, 0, 0, 1); + glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); + + if(!no_lighting) + { + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + float params[4]; + params[0]=0; + params[1]=-0.2; + params[2]=1; + params[3]=0; + glLightfv(GL_LIGHT0, GL_POSITION, params); + } + + //glEnable(GL_DEPTH_TEST); + glEnable(GL_MULTISAMPLE); + + layout_3d.render(); + + glDisable(GL_LIGHTING); + glColor4f(1, 1, 1, 1); + const Track3DSeq <racks=layout_3d.get_tracks(); + for(Track3DSeq::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) + { + Track &track=(*i)->get_track(); + if(track.get_turnout_id()) + { + Turnout *trnt=control.get_turnout(track.get_turnout_id()); + if(trnt) + (*i)->render_route(trnt->get_route()); + else + (*i)->render_route(-1); + } + else + (*i)->render_route(-1); + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, screen_w, 0, screen_h, 0, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_MULTISAMPLE); + + main_panel->render(); + for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i) + (*i)->render(); + + glLoadIdentity(); + glTranslatef(340, 10, 0); + glScalef(20, 20, 20); + glColor4f(1, 1, 1, 1); + font->draw_string(status_text); + + SDL_GL_SwapBuffers(); +} + +void Engineer::key_press(unsigned, unsigned) +{ +} + +void Engineer::button_press(int x, int y, unsigned btn) +{ + if(main_panel->get_geometry().is_inside(x, y)) + { + main_panel->button_press(x, y, btn); + return; + } + for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i) + if((*i)->get_geometry().is_inside(x, y)) + { + (*i)->button_press(x, y, btn); + return; + } + + Track3D *track=pick_track(x, y); + if(track) + { + if(placing_train) + { + Section *sect=trfc_man->get_section_by_track(track->get_track()); + } + else + { + Turnout *turnout=control.get_turnout(track->get_track().get_turnout_id()); + if(turnout) + turnout->set_route(1-turnout->get_route()); + } + } +} + +void Engineer::button_release(int x, int y, unsigned btn) +{ + if(main_panel->get_geometry().is_inside(x, y)) + { + main_panel->button_release(x, y, btn); + return; + } + for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i) + if((*i)->get_geometry().is_inside(x, y)) + { + (*i)->button_release(x, y, btn); + return; + } +} + +void Engineer::pointer_motion(int x, int y) +{ + if(main_panel->get_geometry().is_inside(x, y)) + { + main_panel->pointer_motion(x, y); + return; + } + for(TrainPanelSeq::iterator i=train_panels.begin(); i!=train_panels.end(); ++i) + if((*i)->get_geometry().is_inside(x, y)) + { + (*i)->pointer_motion(x, y); + return; + } + + Track3D *track=pick_track(x, y); + if(track && track->get_track().get_turnout_id()) + { + ostringstream ss; + ss<<"Turnout "<get_track().get_turnout_id(); + status_text=ss.str(); + } + else + status_text=""; +} + +void Engineer::view_all() +{ + const Track3DSeq &tracks=layout_3d.get_tracks(); + + cam_rot=0; + float best_height=-1; + float mid_x=0; + float mid_y=0; + for(float angle=0; angleget_bounds(angle, minp, maxp); + min_x=min(min_x, minp.x); + max_x=max(max_x, maxp.x); + min_y=min(min_y, minp.y); + max_y=max(max_y, maxp.y); + } + + float width=max_x-min_x; + float height=max_y-min_y; + height=max(height, width); + + if(heightget_track().get_sensor_id()==addr) + { + if(state) + (*i)->set_color(Color(1, 0, 0)); + else + (*i)->set_color(Color(1, 1, 1)); + } +} + +void Engineer::project_3d() +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + //glFrustum(-0.055228, 0.055228, -0.041421, 0.041421, 0.1, 10); + glFrustum(-0.069036, 0.041421, -0.041421, 0.041421, 0.1, 10); + glMatrixMode(GL_MODELVIEW); +} + +Track3D *Engineer::pick_track(int x, int y) +{ + float xx=((float)(x-(int)screen_w*5/8)/screen_h)*0.82843; + //float xx=((float)(x-(int)screen_w/2)/screen_h)*0.82843; + float yy=((float)y/screen_h-0.5)*0.82843; + float size=(float)4/screen_h*0.82843; + + project_3d(); + glLoadIdentity(); + glRotatef(-cam_rot*180/M_PI, 0, 0, 1); + glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); + + return layout_3d.pick_track(xx, yy, size); + + /*unsigned select_buf[1024]; + glSelectBuffer(1024, select_buf); + glRenderMode(GL_SELECT); + + //XXX Hardcoded values + float xn=((float)(x-800)/960)*0.082843; + float yn=((float)(y-480)/960)*0.082843; + float size=(float)4/960*0.082843; + + project_3d(); + glLoadIdentity(); + + double clip[4]; + clip[0]=0.1; + clip[1]=0; + clip[2]=xn-size; + clip[3]=0; + glClipPlane(GL_CLIP_PLANE0, clip); + glEnable(GL_CLIP_PLANE0); + + clip[0]=-0.1; + clip[2]=-(xn+size); + glClipPlane(GL_CLIP_PLANE1, clip); + glEnable(GL_CLIP_PLANE1); + + clip[0]=0; + clip[1]=0.1; + clip[2]=yn-size; + glClipPlane(GL_CLIP_PLANE2, clip); + glEnable(GL_CLIP_PLANE2); + + clip[1]=-0.1; + clip[2]=-(yn+size); + glClipPlane(GL_CLIP_PLANE3, clip); + glEnable(GL_CLIP_PLANE3); + + glRotatef(-cam_rot*180/M_PI, 0, 0, 1); + glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); + + layout_3d.render(); + + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + + unsigned n_records=glRenderMode(GL_RENDER); + if(n_records) + { + Track *track=0; + unsigned i=0; + unsigned track_depth=numeric_limits::max(); + for(unsigned j=0; j Engineer::reg; diff --git a/source/engineer/engineer.h b/source/engineer/engineer.h new file mode 100644 index 0000000..112e52f --- /dev/null +++ b/source/engineer/engineer.h @@ -0,0 +1,65 @@ +#ifndef ENGINEER_H_ +#define ENGINEER_H_ + +#include +#include +#include +#include "libmarklin/catalogue.h" +#include "libmarklin/control.h" +#include "libmarklin/trafficmanager.h" +#include "3d/layout.h" + +class MainPanel; +class TrainPanel; + +class Engineer: public Msp::Application +{ +public: + Engineer(int argc, char **argv); + ~Engineer(); + + Marklin::Control &get_control() { return control; } + unsigned get_screen_width() const { return screen_w; } + unsigned get_screen_height() const { return screen_h; } + unsigned get_font_size() const { return font_size; } + Msp::GL::Font &get_font() { return *font; } + void add_train(unsigned); + int main(); + void quit() { exit(0); } +private: + typedef std::list TrainPanelSeq; + + unsigned screen_w; + unsigned screen_h; + unsigned font_size; + bool fullscreen; + Msp::GL::Font *font; + Marklin::Catalogue catalogue; + Marklin::Layout layout; + Marklin::Layout3D layout_3d; + Marklin::Control control; + Marklin::Point cam_pos; + float cam_rot; + Msp::GLtk::Resources ui_res; + MainPanel *main_panel; + TrainPanelSeq train_panels; + std::string status_text; + bool no_lighting; + Marklin::TrafficManager *trfc_mgr; + Train *placing_train; + + void tick(); + void key_press(unsigned, unsigned); + void button_press(int, int, unsigned); + void button_release(int, int, unsigned); + void pointer_motion(int, int); + void view_all(); + void turnout_route_changed(unsigned); + void sensor_state_changed(bool, unsigned); + void project_3d(); + Marklin::Track3D *pick_track(int, int); + + static Msp::Application::RegApp reg; +}; + +#endif diff --git a/source/engineer/guicomponent.h b/source/engineer/guicomponent.h new file mode 100644 index 0000000..f752936 --- /dev/null +++ b/source/engineer/guicomponent.h @@ -0,0 +1,44 @@ +#ifndef GUICOMPONENT_H_ +#define GUICOMPONENT_H_ + +class GuiComponent +{ +public: + enum HAlign + { + LEFT, + CENTER, + RIGHT + }; + + enum VAlign + { + TOP, + MIDDLE, + BOTTOM + }; + + struct Part + { + enum Type + { + IMAGE, + LABEL, + TEXT + }; + + std::string variation; + std::string state; + Type type; + std::string data; + HAlign align_x; + VAlign align_y; + int offset_x; + int offset_y; + }; + typedef std::list PartSeq; + +private: +}; + +#endif diff --git a/source/engineer/guiresources.h b/source/engineer/guiresources.h new file mode 100644 index 0000000..86d29ce --- /dev/null +++ b/source/engineer/guiresources.h @@ -0,0 +1,4 @@ +#ifndef GUIRESOURCES_H_ +#define GUIRESOURCES_H_ + +#endif diff --git a/source/engineer/mainpanel.cpp b/source/engineer/mainpanel.cpp new file mode 100644 index 0000000..7e68c03 --- /dev/null +++ b/source/engineer/mainpanel.cpp @@ -0,0 +1,70 @@ +#include +#include "engineer.h" +#include "mainpanel.h" + +using namespace Msp; + +MainPanel::MainPanel(Engineer &e, GLtk::Resources &r): + Panel(r), + engineer(e) +{ + set_size(200, 100); + + GLtk::Button *btn; + + add(*(btn=new GLtk::Button(res, "Off"))); + btn->set_geometry(GLtk::Geometry(10, 50, 40, 25)); + btn->set_style("red"); + btn->signal_clicked.connect(sigc::mem_fun(this, &MainPanel::power_off)); + + add(*(ind_off=new GLtk::Indicator(res))); + ind_off->set_geometry(GLtk::Geometry(10, 78, 40, 12)); + ind_off->set_style("red"); + + add(*(btn=new GLtk::Button(res, "On"))); + btn->set_geometry(GLtk::Geometry(50, 50, 40, 25)); + btn->set_style("green"); + btn->signal_clicked.connect(sigc::mem_fun(this, &MainPanel::power_on)); + + add(*(ind_on=new GLtk::Indicator(res))); + ind_on->set_geometry(GLtk::Geometry(50, 78, 40, 12)); + ind_on->set_style("green"); + + add(*(btn=new GLtk::Button(res, "Quit"))); + btn->set_geometry(GLtk::Geometry(150, 50, 40, 25)); + btn->set_style("red"); + btn->signal_clicked.connect(sigc::mem_fun(this, &MainPanel::quit)); + + add(*(btn=new GLtk::Button(res, "+Loc"))); + btn->set_geometry(GLtk::Geometry(10, 10, 40, 25)); + btn->signal_clicked.connect(sigc::mem_fun(this, &MainPanel::new_loc)); + + if(engineer.get_control().get_power()) + ind_on->set_active(true); + else + ind_off->set_active(true); +} + +void MainPanel::power_on() +{ + engineer.get_control().set_power(true); + ind_on->set_active(true); + ind_off->set_active(false); +} + +void MainPanel::power_off() +{ + engineer.get_control().set_power(false); + ind_on->set_active(false); + ind_off->set_active(true); +} + +void MainPanel::new_loc() +{ + engineer.add_train(0); +} + +void MainPanel::quit() +{ + engineer.quit(); +} diff --git a/source/engineer/mainpanel.h b/source/engineer/mainpanel.h new file mode 100644 index 0000000..3d9a2b7 --- /dev/null +++ b/source/engineer/mainpanel.h @@ -0,0 +1,24 @@ +#ifndef MAINPANEL_H_ +#define MAINPANEL_H_ + +#include +#include + +class Engineer; + +class MainPanel: public Msp::GLtk::Panel +{ +public: + MainPanel(Engineer &, Msp::GLtk::Resources &); +private: + Engineer &engineer; + Msp::GLtk::Indicator *ind_on; + Msp::GLtk::Indicator *ind_off; + + void power_on(); + void power_off(); + void new_loc(); + void quit(); +}; + +#endif diff --git a/source/engineer/trainpanel.cpp b/source/engineer/trainpanel.cpp new file mode 100644 index 0000000..d9a8c77 --- /dev/null +++ b/source/engineer/trainpanel.cpp @@ -0,0 +1,36 @@ +#include +#include "trainpanel.h" + +using namespace Msp; +using namespace Marklin; + +TrainPanel::TrainPanel(Engineer &e, const GLtk::Resources &r, Train &t): + Panel(r), + engineer(e), + train(t) +{ + set_size(200, 100); + + add(*(lbl_name=new GLtk::Label(res, "Train 1"))); + lbl_name->set_style("digital"); + lbl_name->set_geometry(GLtk::Geometry(10, geom.h-34, 140, 24)); + + GLtk::Button *btn; + + add(*(btn=new GLtk::Button(res, "Name"))); + btn->set_geometry(GLtk::Geometry(150, geom.h-34, 40, 24)); + + add(*(sld_speed=new GLtk::HSlider(res))); + sld_speed->set_geometry(GLtk::Geometry(10, geom.h-49, 180, 10)); + sld_speed->set_range(0, 14); + sld_speed->set_step(1); + sld_speed->signal_value_changed.connect(sigc::mem_fun(this, &TrainPanel::speed_slider_changed)); + + add(*(btn=new GLtk::Button(res, "Place"))); + btn->set_geometry(GLtk::Geometry(150, geom.h-75, 40, 24)); +} + +void TrainPanel::speed_slider_changed(double v) +{ + train.set_speed(static_cast(v)); +} diff --git a/source/engineer/trainpanel.h b/source/engineer/trainpanel.h new file mode 100644 index 0000000..79b9d49 --- /dev/null +++ b/source/engineer/trainpanel.h @@ -0,0 +1,25 @@ +#ifndef TRAINPANEL_H_ +#define TRAINPANEL_H_ + +#include +#include +#include +#include "libmarklin/train.h" + +class Engineer; + +class TrainPanel: public Msp::GLtk::Panel +{ +public: + TrainPanel(Engineer &, const Msp::GLtk::Resources &, Marklin::Train &); +private: + Engineer &engineer; + Marklin::Train &train; + Msp::GLtk::Label *lbl_name; + Msp::GLtk::HSlider *sld_speed; + Marklin::Locomotive *loco; + + void speed_slider_changed(double); +}; + +#endif diff --git a/source/libmarklin/catalogue.cpp b/source/libmarklin/catalogue.cpp new file mode 100644 index 0000000..3c8e279 --- /dev/null +++ b/source/libmarklin/catalogue.cpp @@ -0,0 +1,63 @@ +#include +#include +#include "catalogue.h" +#include "track.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Track *Catalogue::get_track(unsigned art_nr) +{ + TrackMap::const_iterator i=tracks.find(art_nr); + + if(i!=tracks.end()) + return i->second; + + return 0; +} + +void Catalogue::load(const string &fn) +{ + ifstream in(fn.c_str()); + if(!in) + throw Exception("File not found"); + + Parser::Parser parser(in, fn); + Loader loader(*this); + loader.load(parser); +} + +Catalogue::~Catalogue() +{ + for(TrackMap::iterator i=tracks.begin(); i!=tracks.end(); ++i) + delete i->second; +} + +Catalogue::Loader::Loader(Catalogue &c): + cat(c) +{ + add("track", &Loader::track); +} + +void Catalogue::Loader::track(unsigned art_no) +{ + TrackMap::iterator i=cat.tracks.find(art_no); + if(i!=cat.tracks.end()) + throw Exception("Duplicate track number"); + + Track *trk=new Track(art_no); + try + { + load_sub(*trk); + } + catch(const Msp::Exception &) + { + delete trk; + throw; + } + cat.tracks.insert(TrackMap::value_type(trk->get_article_number(), trk)); +} + +} // namespace Marklin diff --git a/source/libmarklin/catalogue.h b/source/libmarklin/catalogue.h new file mode 100644 index 0000000..1a328bb --- /dev/null +++ b/source/libmarklin/catalogue.h @@ -0,0 +1,35 @@ +#ifndef LIBMARKLIN_CATALOGUE_H_ +#define LIBMARKLIN_CATALOGUE_H_ + +#include +#include + +namespace Marklin { + +class Track; + +class Catalogue +{ +public: + class Loader: public Msp::Parser::Loader + { + public: + Loader(Catalogue &); + private: + Catalogue &cat; + + void track(unsigned); + }; + typedef std::map TrackMap; + + Track *get_track(unsigned); + const TrackMap &get_tracks() const { return tracks; } + void load(const std::string &); + ~Catalogue(); +private: + TrackMap tracks; +}; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/command.h b/source/libmarklin/command.h new file mode 100644 index 0000000..2106d23 --- /dev/null +++ b/source/libmarklin/command.h @@ -0,0 +1,26 @@ +#ifndef COMMAND_H_ +#define COMMAND_H_ + +#include +#include +#include "constants.h" + +namespace Marklin { + +class Command +{ +public: + sigc::signal signal_done; + + Command(const std::string &c): cmd(c), sent(false) { } + void set_sent(bool s) { sent=s; } + const std::string &get_command() const { return cmd; } + bool get_sent() const { return sent; } +private: + std::string cmd; + bool sent; +}; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/constants.h b/source/libmarklin/constants.h new file mode 100644 index 0000000..2db75c2 --- /dev/null +++ b/source/libmarklin/constants.h @@ -0,0 +1,52 @@ +#ifndef ERROR_H_ +#define ERROR_H_ + +namespace Marklin { + +enum Error +{ + ERR_NO_ERROR=0, + ERR_SYS_ERROR, + ERR_BAD_PARAM, + ERR_POWER_OFF=0x6, + ERR_NO_LOK_SPACE=0x8, // No space in lok command buffer + ERR_NO_TURNOUT_SPACE, // No space in turnout command buffer + ERR_NO_DATA, // "no Lok status available (Lok is not in a slot)" + ERR_NO_SLOT, // "there is no slot available" + ERR_BAD_LOK_ADDR, + ERR_LOK_BUSY, + ERR_BAD_TURNOUT_ADDR, + ERR_BAD_SO_VALUE, + ERR_NO_I2C_SPACE, + ERR_LOW_TURNOUT_SPACE=0x40, + ERR_LOK_HALTED, + ERR_LOK_POWER_OFF, + ERR_UNKNOWN_ERROR=0xFF +}; + +enum Cmd +{ + CMD_LOK=0x80, + CMD_LOK_STATUS=0x84, + CMD_LOK_CONFIG=0x85, + CMD_FUNC=0x88, + CMD_FUNC_STATUS=0x8C, + CMD_TURNOUT=0x90, + CMD_TURNOUT_FREE=0x93, + CMD_TURNOUT_STATUS=0x94, + CMD_TURNOUT_GROUP_STATUS=0x95, + CMD_SENSOR_STATUS=0x98, + CMD_SENSOR_REPORT=0x99, + CMD_SENSOR_PARAM_SET=0x9D, + CMD_POWER_OFF=0xA6, + CMD_POWER_ON=0xA7, + CMD_NOP=0xC4, + CMD_EVENT=0xC8, + CMD_EVENT_LOK=0xC9, + CMD_EVENT_TURNOUT=0xCA, + CMD_EVENT_SENSOR=0xCB +}; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/control.cpp b/source/libmarklin/control.cpp new file mode 100644 index 0000000..d371777 --- /dev/null +++ b/source/libmarklin/control.cpp @@ -0,0 +1,329 @@ +#include +#include +#include +#include +#include +#include +#include +#include "command.h" +#include "control.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Control::Control(): + serial_fd(-1), + p50_enabled(false), + power(true), + poll_sensors(false), + debug(false) +{ } + +void Control::set_power(bool p) +{ + power=p; + if(power) + command(string(1, CMD_POWER_ON)); + else + command(string(1, CMD_POWER_OFF)); +} + +Turnout *Control::get_turnout(unsigned id) const +{ + TurnoutMap::const_iterator i=turnouts.find(id); + if(i!=turnouts.end()) + return i->second; + + return 0; +} + +Locomotive *Control::get_locomotive(unsigned id) const +{ + for(LocomotiveSeq::const_iterator i=locomotives.begin(); i!=locomotives.end(); ++i) + if((*i)->get_address()==id) + return *i; + return 0; +} + +Sensor *Control::get_sensor(unsigned id) const +{ + SensorMap::const_iterator i=sensors.find(id); + if(i!=sensors.end()) + return i->second; + + return 0; +} + +void Control::open(const string &dev) +{ + serial_fd=::open(dev.c_str(), O_RDWR); + if(serial_fd<0) + throw Exception("Couldn't open serial port\n"); + + static unsigned baud[]= + { + 2400, B2400, + 4800, B4800, + 9600, B9600, + 19200, B19200, + 0 + }; + + termios attr; + tcgetattr(serial_fd, &attr); + cfmakeraw(&attr); + attr.c_cflag|=CSTOPB; + + bool ok=false; + for(unsigned i=0; baud[i]; i+=2) + { + cfsetospeed(&attr, baud[i+1]); + tcsetattr(serial_fd, TCSADRAIN, &attr); + + write(serial_fd, "\xC4", 1); + + pollfd pfd={serial_fd, POLLIN, 0}; + if(poll(&pfd, 1, 500)>0) + { + cout<<"IB detected at "<get_address())==0) + turnouts.insert(TurnoutMap::value_type(t->get_address(), t)); +} + +void Control::add_locomotive(Locomotive *l) +{ + if(find(locomotives.begin(), locomotives.end(), l)==locomotives.end()) + locomotives.push_back(l); +} + +void Control::add_sensor(Sensor *s) +{ + if(sensors.count(s->get_address())==0) + { + sensors.insert(SensorMap::value_type(s->get_address(), s)); + poll_sensors=true; + } +} + +void Control::tick() +{ + const Time::TimeStamp t=Time::now(); + + if(t>next_event_query) + { + next_event_query=t+300*Time::msec; + command(string(1, CMD_EVENT)).signal_done.connect(sigc::mem_fun(this, &Control::event_query_done)); + } + + if(poll_sensors) + { + unsigned max_addr=(--sensors.end())->second->get_address(); + string cmd(3, 0); + cmd[0]=CMD_SENSOR_PARAM_SET; + cmd[1]=0; + cmd[2]=(max_addr+7)/8; + command(cmd); + command(string(1, CMD_SENSOR_REPORT)); + poll_sensors=false; + } + + if(queue.size() && queue.front().get_sent()) + { + pollfd pfd={serial_fd, POLLIN, 0}; + if(poll(&pfd, 1, 0)>0) + { + string resp=read_reply((Cmd)(unsigned char)queue.front().get_command()[0]); + if(debug) + { + printf("read: "); + for(unsigned i=0; i>(7-j%8))&1; + cout< +#include +#include +#include "constants.h" +#include "sensor.h" +#include "locomotive.h" +#include "turnout.h" + +namespace Marklin { + +class Command; + +class Control +{ +public: + sigc::signal signal_turnout_event; + sigc::signal signal_sensor_event; + + Control(); + void set_power(bool); + void set_debug(bool d) { debug=d; } + bool get_power() const { return power; } + const TurnoutMap &get_turnouts() const { return turnouts; } + Turnout *get_turnout(unsigned) const; + Locomotive *get_locomotive(unsigned) const; + Sensor *get_sensor(unsigned) const; + unsigned get_queue_length() const { return queue.size(); } + void open(const std::string &); + Command &command(const std::string &); + void add_turnout(Turnout *); + void add_locomotive(Locomotive *); + void add_sensor(Sensor *); + void tick(); + ~Control(); +private: + int serial_fd; + bool p50_enabled; + bool power; + std::list queue; + TurnoutMap turnouts; + LocomotiveSeq locomotives; + SensorMap sensors; + Msp::Time::TimeStamp next_event_query; + bool poll_sensors; + bool debug; + + void read_all(int, char *, int); + std::string read_reply(Cmd); + void event_query_done(Error, const std::string &); + void turnout_event_done(Error, const std::string &); + void sensor_event_done(Error, const std::string &); +}; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/geometry.h b/source/libmarklin/geometry.h new file mode 100644 index 0000000..9dee86e --- /dev/null +++ b/source/libmarklin/geometry.h @@ -0,0 +1,18 @@ +#ifndef LIBMARKLIN_GEOMETRY_H_ +#define LIBMARKLIN_GEOMETRY_H_ + +#include + +namespace Marklin { + +struct Point +{ + float x,y,z; + + Point(): x(0), y(0), z(0) { } + Point(float x_, float y_, float z_): x(x_), y(y_), z(z_) { } +}; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/layout.cpp b/source/libmarklin/layout.cpp new file mode 100644 index 0000000..1fe06c7 --- /dev/null +++ b/source/libmarklin/layout.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include "catalogue.h" +#include "layout.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Layout::Layout(Catalogue &c): + catalogue(c) +{ } + +void Layout::add_track(Track *t) +{ + if(find(tracks.begin(), tracks.end(), t)==tracks.end()) + { + tracks.push_back(t); + signal_track_added.emit(t); + } +} + +void Layout::remove_track(Track *t) +{ + TrackSeq::iterator i=remove_if(tracks.begin(), tracks.end(), bind1st(equal_to(), t)); + if(i!=tracks.end()) + { + tracks.erase(i, tracks.end()); + signal_track_removed.emit(t); + } +} + +void Layout::check_links() +{ + for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + (*i)->break_links(); + + for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + for(TrackSeq::iterator j=i; j!=tracks.end(); ++j) + if(j!=i) + (*i)->snap_to(**j, true); +} + +void Layout::load(const string &fn) +{ + ifstream in(fn.c_str()); + if(!in) + throw Exception("Couldn't open file"); + + filename=fn; + Parser::Parser parser(in, fn); + Loader loader(*this); + loader.load(parser); + + check_links(); + + for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + (*i)->check_slope(); +} + +int Layout::save(const string &fn) +{ + ofstream out(fn.c_str()); + if(!out) return -1; + + filename=fn; + + if(base.size()) + out<<"base \""<get_article_number()<<"\n{\n"; + const Point &p=(*i)->get_position(); + out<<"\tposition "<get_rotation()<<";\n"; + out<<"\tslope "<<(*i)->get_slope()<<";\n"; + + unsigned id=(*i)->get_turnout_id(); + if(id) + out<<"\tturnout_id "<get_sensor_id(); + if(id) + out<<"\tsensor_id "<get_flex()) + out<<"\tflex true;\n"; + + out<<"};\n"; + } + + return 0; +} + +Layout::~Layout() +{ + for(TrackSeq::iterator i=tracks.begin(); i!=tracks.end(); ++i) + delete *i; +} + +/******************* +** Layout::Loader +*/ + +Layout::Loader::Loader(Layout &l): + layout(l) +{ + add("base", &Layout::base); + add("track", &Loader::track); +} + +void Layout::Loader::track(unsigned art_nr) +{ + Track *tmpl=layout.catalogue.get_track(art_nr); + if(!tmpl) + throw Exception("Unknown track"); + + Track *trk=tmpl->copy(); + try + { + load_sub(*trk); + } + catch(Msp::Exception &e) + { + delete trk; + throw; + } + layout.tracks.push_back(trk); + layout.signal_track_added.emit(trk); +} + +} // namespace Marklin diff --git a/source/libmarklin/layout.h b/source/libmarklin/layout.h new file mode 100644 index 0000000..c292af6 --- /dev/null +++ b/source/libmarklin/layout.h @@ -0,0 +1,49 @@ +#ifndef LIBMARKLIN_LAYOUT_H_ +#define LIBMARKLIN_LAYOUT_H_ + +#include +#include +#include "route.h" +#include "track.h" + +namespace Marklin { + +class Catalogue; + +class Layout +{ +public: + class Loader: public Msp::Parser::Loader + { + public: + Loader(Layout &); + Layout &get_object() { return layout; } + private: + Layout &layout; + + void track(unsigned); + }; + + sigc::signal signal_track_added; + sigc::signal signal_track_removed; + + Layout(Catalogue &); + const TrackSeq &get_tracks() const { return tracks; } + void add_track(Track *); + void remove_track(Track *); + void check_links(); + void load(const std::string &); + int save(const std::string &); + ~Layout(); +private: + Catalogue &catalogue; + std::string filename; + std::string base; + TrackSeq tracks; + RouteSeq routes; +}; + +} // namespace Marklin + +#endif + diff --git a/source/libmarklin/locomotive.cpp b/source/libmarklin/locomotive.cpp new file mode 100644 index 0000000..ecacea1 --- /dev/null +++ b/source/libmarklin/locomotive.cpp @@ -0,0 +1,116 @@ +#include +#include +#include "command.h" +#include "constants.h" +#include "control.h" +#include "locomotive.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Locomotive::Locomotive(Control &c, unsigned a): + control(c), + addr(a), + speed(0), + reverse(false), + funcs(0) +{ + control.add_locomotive(this); + + refresh_status(); +} + +void Locomotive::set_speed(unsigned spd) +{ + speed=min(spd, 14U); + + send_command(false); +} + +void Locomotive::set_reverse(bool rev) +{ + if(rev==reverse) + return; + + if(speed) + { + (new Time::Timer((500+speed*150)*Time::msec))->signal_timeout.connect(sigc::mem_fun(this, &Locomotive::reverse_timeout)); + set_speed(0); + } + else + { + reverse=rev; + send_command(false); + } +} + +void Locomotive::set_function(unsigned func, bool state) +{ + if(state) + funcs|=1<>8)&0xFF; + control.command(string(cmd,3)).signal_done.connect(sigc::mem_fun(this,&Locomotive::status_reply)); +} + +void Locomotive::send_command(bool setf) +{ + char cmd[16]; + cmd[0]=CMD_LOK; + cmd[1]=addr&0xFF; + cmd[2]=(addr>>8)&0xFF; + + if(speed==0) + cmd[3]=0; + else if(speed==1) + cmd[3]=2; + else + cmd[3]=(speed*19-18)/2; + + cmd[4]=(reverse?0:0x20) | ((funcs&1)?0x10:0); + + if(setf) + { + cmd[4]|=0x80; + for(unsigned i=0; i<4; ++i) + if((funcs>>i)&2) + cmd[4]|=(1< +#include +#include "constants.h" + +namespace Marklin { + +class Control; + +class Locomotive +{ +public: + Locomotive(Control &, unsigned); + void set_speed(unsigned); + void set_reverse(bool); + void set_function(unsigned, bool); + unsigned get_address() const { return addr; } + unsigned get_speed() const { return speed; } + bool get_reverse() const { return reverse; } + bool get_function(unsigned f) const { return (funcs>>f)&1; } + void refresh_status(); +private: + Control &control; + unsigned addr; + unsigned speed; + bool reverse; + unsigned funcs; + + void send_command(bool); + void status_reply(Error, const std::string &); + bool reverse_timeout(); +}; +typedef std::list LocomotiveSeq; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/route.cpp b/source/libmarklin/route.cpp new file mode 100644 index 0000000..9894398 --- /dev/null +++ b/source/libmarklin/route.cpp @@ -0,0 +1,7 @@ +#include "route.h" + +namespace Marklin { + + + +} // namespace Marklin diff --git a/source/libmarklin/route.h b/source/libmarklin/route.h new file mode 100644 index 0000000..f5b7602 --- /dev/null +++ b/source/libmarklin/route.h @@ -0,0 +1,28 @@ +#ifndef LIBMARKLIN_ROUTE_H_ +#define LIBMARKLIN_ROUTE_H_ + +#include +#include +#include "track.h" + +namespace Marklin { + +class Route +{ +public: + typedef std::map TurnoutMap; + + Route(); + const TurnoutMap &get_turnouts() const { return turnouts; } + void add_track(Track *); + ~Route(); +private: + std::string name; + TrackSeq tracks; + TurnoutMap turnouts; +}; +typedef std::list RouteSeq; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/section.cpp b/source/libmarklin/section.cpp new file mode 100644 index 0000000..17a0ce4 --- /dev/null +++ b/source/libmarklin/section.cpp @@ -0,0 +1,183 @@ +#include "control.h" +#include "section.h" +#include "trafficmanager.h" +#include "turnout.h" + +using namespace Msp; + +#include +using namespace std; + +namespace Marklin { + +Section::Section(TrafficManager &tm, Track *start): + trfc_mgr(tm), + id(next_id++), + sensor_id(0), + train(0) +{ + tracks.insert(start); + + if(start->get_sensor_id()) + { + sensor_id=start->get_sensor_id(); + const Track::EndpointSeq &eps=start->get_endpoints(); + for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i) + endpoints.push_back(Endpoint(start, &*i)); + } + else + { + TrackSeq queue; + queue.push_back(start); + + while(!queue.empty()) + { + Track *track=queue.front(); + queue.erase(queue.begin()); + + const Track::EndpointSeq &eps=track->get_endpoints(); + for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i) + if(i->link && tracks.count(i->link)==0) + { + if(!i->link->get_sensor_id()) + { + queue.push_back(i->link); + tracks.insert(i->link); + } + else + endpoints.push_back(Endpoint(track, &*i)); + } + } + } + + unsigned n=0; + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i, ++n) + { + unsigned route=1<routes|=route; + set visited; + find_routes(i->track, i->track_ep, route, visited); + } +} + +const Section::Endpoint *Section::get_endpoint_by_link(const Section *other) const +{ + for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->link==other) + return &*i; + + return 0; +} + +const Section::Endpoint *Section::traverse(const Endpoint *ep) const +{ + Track *track=ep->track; + const Track::Endpoint *track_ep=ep->track_ep; + + while(1) + { + unsigned cur_route=0; + unsigned tid=track->get_turnout_id(); + if(tid) + { + Turnout *turnout=trfc_mgr.get_control().get_turnout(tid); + if(turnout) + cur_route=turnout->get_route(); + } + + const Track::Endpoint *other_ep=track->traverse(track_ep, cur_route); + if(!other_ep) + return 0; + + for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->track==track && i->track_ep==other_ep) + return &*i; + + track_ep=track->get_endpoint_by_link(other_ep->link); + track=other_ep->link; + + if(tracks.count(track)==0) + return 0; + } +} + +void Section::check_link(Section &other) +{ + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + { + if(i->link) + continue; + + for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j) + if(j->track==i->track_ep->link && j->track_ep->link==i->track && !j->link) + { + i->link=&other; + j->link=this; + } + } +} + +bool Section::reserve(const Train *t) +{ + if(!t || !train) + { + train=t; + return true; + } + else + return false; +} + +void Section::print_debug() +{ + cout<<"Section "<get_sensor_id()) + cout<<", sensor="<<(*tracks.begin())->get_sensor_id(); + cout<<'\n'; + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + { + cout<<" Endpoint, link="; + if(i->link) + cout<link->id; + else + cout<<"none"; + cout<<", routes="<routes<<'\n'; + } +} + +void Section::find_routes(Track *track, const Track::Endpoint *track_ep, unsigned route, std::set &visited) +{ + visited.insert(track); + + const Track::EndpointSeq &eps=track->get_endpoints(); + for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i) + { + if(&*i==track_ep) continue; + if(!i->link) continue; + if(!(i->routes&track_ep->routes)) continue; + if(visited.count(i->link)) continue; + + if(tracks.count(i->link)) + find_routes(i->link, i->link->get_endpoint_by_link(track), route, visited); + else + { + for(EndpointSeq::iterator j=endpoints.begin(); j!=endpoints.end(); ++j) + if(j->track==track && j->track_ep==&*i) + j->routes|=route; + } + } + + visited.erase(--visited.end()); +} + +unsigned Section::next_id=1; + + +Section::Endpoint::Endpoint(Track *t, const Track::Endpoint *e): + track(t), + track_ep(e), + link(0), + routes(0) +{ } + +} // namespace Marklin diff --git a/source/libmarklin/section.h b/source/libmarklin/section.h new file mode 100644 index 0000000..679466f --- /dev/null +++ b/source/libmarklin/section.h @@ -0,0 +1,51 @@ +#ifndef MARKLIN_3D_SECTION_H_ +#define MARKLIN_3D_SECTION_H_ + +#include +#include +#include "track.h" + +namespace Marklin { + +class Train; +class TrafficManager; + +class Section +{ +public: + struct Endpoint + { + Track *track; + const Track::Endpoint *track_ep; + Section *link; + unsigned routes; + + Endpoint(Track *, const Track::Endpoint *); + }; + typedef std::list EndpointSeq; + + Section(TrafficManager &, Track *); + unsigned get_sensor_id() const { return sensor_id; } + const TrackSet &get_tracks() const { return tracks; } + const Endpoint *get_endpoint_by_link(const Section *) const; + const Endpoint *traverse(const Endpoint *) const; + void check_link(Section &); + bool reserve(const Train *); + void print_debug(); +private: + TrafficManager &trfc_mgr; + unsigned id; + unsigned sensor_id; + TrackSet tracks; + EndpointSeq endpoints; + const Train *train; + + void find_routes(Track *, const Track::Endpoint *, unsigned, TrackSet &); + + static unsigned next_id; +}; +typedef std::list
SectionSeq; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/sensor.cpp b/source/libmarklin/sensor.cpp new file mode 100644 index 0000000..f6913ba --- /dev/null +++ b/source/libmarklin/sensor.cpp @@ -0,0 +1,24 @@ +#include "control.h" +#include "sensor.h" + +namespace Marklin { + +Sensor::Sensor(Control &c, unsigned a): + control(c), + addr(a), + state(false) +{ + control.add_sensor(this); + control.signal_sensor_event.connect(sigc::mem_fun(this, &Sensor::sensor_event)); +} + +void Sensor::sensor_event(unsigned a, bool s) +{ + if(a==addr && s!=state) + { + state=s; + signal_state_changed.emit(state); + } +} + +} // namespace Marklin diff --git a/source/libmarklin/sensor.h b/source/libmarklin/sensor.h new file mode 100644 index 0000000..e5e1b43 --- /dev/null +++ b/source/libmarklin/sensor.h @@ -0,0 +1,32 @@ +#ifndef LIBMARKLIN_SENSOR_H_ +#define LIBMARKLIN_SENSOR_H_ + +#include +#include +#include + +namespace Marklin { + +class Control; + +class Sensor +{ +public: + sigc::signal signal_state_changed; + + Sensor(Control &, unsigned); + unsigned get_address() const { return addr; } + bool get_state() const { return state; } +private: + Control &control; + unsigned addr; + bool state; + + void sensor_event(unsigned, bool); +}; +typedef std::list SensorSeq; +typedef std::map SensorMap; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/track.cpp b/source/libmarklin/track.cpp new file mode 100644 index 0000000..aaf1b75 --- /dev/null +++ b/source/libmarklin/track.cpp @@ -0,0 +1,374 @@ +#include +#include "track.h" + +using namespace std; +using namespace Msp; + +#include + +namespace Marklin { + +Track::Track(unsigned a): + art_nr(a), + rot(0), + slope(0), + flex(false), + turnout_id(0), + sensor_id(0) +{ } + +Track::~Track() +{ + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->link) + { + Track *trk=i->link; + i->link=0; + trk->break_link(*this); + } +} + +void Track::set_position(const Point &p) +{ + pos=p; +} + +void Track::set_rotation(float r) +{ + rot=r; + while(rot<0) + rot+=M_PI*2; + while(rot>M_PI*2) + rot-=M_PI*2; +} + +void Track::set_slope(float s) +{ + if(endpoints.size()!=2) return; + + slope=s; + endpoints.back().pos.z=slope; +} + +const Track::Endpoint *Track::get_endpoint_by_link(Track *other) const +{ + for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->link==other) + return &*i; + + return 0; +} + +float Track::get_length() const +{ + float len=parts.front().length; + if(parts.front().radius) + len*=parts.front().radius; + return len; +} + +float Track::get_total_length() const +{ + float len=0; + for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i) + { + float l=i->length; + if(i->radius) + l*=i->radius; + len+=l; + } + return len; +} + +unsigned Track::get_n_routes() const +{ + unsigned n=1; + for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i) + if(i->route>=n) + n=i->route+1; + return n; +} + +bool Track::snap_to(Track &other, bool link) +{ + float limit=(link && !flex) ? 1e-6 : 1e-4; + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + { + float x=pos.x+i->pos.x*cos(rot)-i->pos.y*sin(rot); + float y=pos.y+i->pos.y*cos(rot)+i->pos.x*sin(rot); + for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j) + { + if(j->link) + continue; + + float x2=other.pos.x+j->pos.x*cos(other.rot)-j->pos.y*sin(other.rot); + float y2=other.pos.y+j->pos.y*cos(other.rot)+j->pos.x*sin(other.rot); + float dx=x2-x; + float dy=y2-y; + if(dx*dx+dy*dyrot-i->rot+M_PI); + set_position(Point(x2-(i->pos.x*cos(rot)-i->pos.y*sin(rot)), y2-(i->pos.y*cos(rot)+i->pos.x*sin(rot)), other.pos.z+j->pos.z-i->pos.z)); + if(link) + { + if(i->link) + break_link(*i->link); + i->link=&other; + j->link=this; + } + return true; + } + } + } + + return false; +} + +bool Track::snap(Point &pt, float &d) const +{ + for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + { + float x=pos.x+i->pos.x*cos(rot)-i->pos.y*sin(rot); + float y=pos.y+i->pos.y*cos(rot)+i->pos.x*sin(rot); + float dx=pt.x-x; + float dy=pt.y-y; + if(dx*dx+dy*dy<1e-4) + { + pt.x=x; + pt.y=y; + d=rot+i->rot; + return true; + } + } + + return false; +} + +void Track::break_link(Track &trk) +{ + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->link==&trk) + { + i->link=0; + trk.break_link(*this); + return; + } +} + +void Track::break_links() +{ + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->link) + { + Track *trk=i->link; + i->link=0; + trk->break_link(*this); + } +} + +void Track::check_slope() +{ + if(endpoints.size()!=2) + return; + + Track *link1=endpoints.front().link; + Track *link2=endpoints.back().link; + if(link1 && link2) + { + const Endpoint *ep1=link1->get_endpoint_by_link(this); + const Endpoint *ep2=link2->get_endpoint_by_link(this); + pos.z=link1->pos.z+ep1->pos.z; + slope=(link2->pos.z+ep2->pos.z)-pos.z; + } + else + { + slope=0; + if(link1) + { + const Endpoint *ep=link1->get_endpoint_by_link(this); + pos.z=link1->pos.z+ep->pos.z; + } + else if(link2) + { + const Endpoint *ep=link2->get_endpoint_by_link(this); + pos.z=link2->pos.z+ep->pos.z; + } + } + + endpoints.back().pos.z=slope; +} + +const Track::Endpoint *Track::traverse(const Endpoint *ep, unsigned route) const +{ + if(ep->routes&(1<routes&(1<routes&(1<routes&ep->routes)) + return &*i; + } + + return 0; +} + +Track *Track::copy() const +{ + Track *trk=new Track(*this); + for(EndpointSeq::iterator i=trk->endpoints.begin(); i!=trk->endpoints.end(); ++i) + i->link=0; + trk->turnout_id=0; + trk->sensor_id=0; + + return trk; +} + +/*** private ***/ + +void Track::collect_endpoints() +{ + endpoints.clear(); + + for(PartSeq::iterator i=parts.begin(); i!=parts.end(); ++i) + i->collect_endpoints(endpoints); + endpoints.back().pos.z=slope; + + for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end();) + { + bool rm=false; + for(EndpointSeq::iterator j=i; j!=endpoints.end();) + { + if(j==i) + { + ++j; + continue; + } + float dx=i->pos.x-j->pos.x; + float dy=i->pos.y-j->pos.y; + if(dx*dx+dy*dy<0.0001) + { + float da=i->rot-j->rot; + if(da<-M_PI) + da+=M_PI*2; + if(da>M_PI) + da-=M_PI*2; + if(da<-3 || da>3) + rm=true; + i->routes|=j->routes; + j=endpoints.erase(j); + } + else + ++j; + } + if(rm) + i=endpoints.erase(i); + else + ++i; + } +} + +/******************* +** Track::Loader +*/ + +Track::Loader::Loader(Track &t): + track(t) +{ + add("description", &Track::description); + add("part", &Loader::part); + add("position", &Loader::position); + add("rotation", &Track::rot); + add("slope", &Track::slope); + add("turnout_id", &Track::turnout_id); + add("sensor_id", &Track::sensor_id); + add("flex", &Track::flex); +} + +Track::Loader::~Loader() +{ + track.collect_endpoints(); +} + +void Track::Loader::part() +{ + Part p; + load_sub(p); + track.parts.push_back(p); +} + +void Track::Loader::position(float x, float y, float z) +{ + track.pos=Point(x, y, z); +} + +/******************* +** Track::Part +*/ + +Track::Part::Part(): + x(0), + y(0), + dir(0), + length(0), + radius(0), + route(0), + dead_end(false) +{ } + +void Track::Part::collect_endpoints(EndpointSeq &epl) +{ + epl.push_back(Endpoint(Point(x, y, 0), dir+M_PI, 1< +#include +#include +#include "geometry.h" + +namespace Marklin { + +class Track +{ +public: + class Loader: public Msp::Parser::Loader + { + public: + Loader(Track &); + Track &get_object() { return track; } + ~Loader(); + private: + Track &track; + + void part(); + void position(float, float, float); + }; + + struct Endpoint + { + Point pos; + float rot; + Track *link; + unsigned routes; + + Endpoint(const Point &p, float r, unsigned o): pos(p), rot(r), link(0), routes(o) { } + }; + typedef std::list EndpointSeq; + + struct Part + { + class Loader: public Msp::Parser::Loader + { + public: + Loader(Part &); + Part &get_object() { return part; } + ~Loader(); + private: + Part ∂ + + void start(float, float, float); + }; + + float x,y; + float dir; + float length; + float radius; + unsigned route; + bool dead_end; + + Part(); + void collect_endpoints(EndpointSeq &); + }; + typedef std::list PartSeq; + + Track(unsigned); + ~Track(); + void set_position(const Point &); + void set_rotation(float); + void set_slope(float); + void set_flex(bool f) { flex=f; } + void set_turnout_id(unsigned i) { turnout_id=i; } + void set_sensor_id(unsigned i) { sensor_id=i; } + const Point &get_position() const { return pos; } + float get_rotation() const { return rot; } + unsigned get_article_number() const { return art_nr; } + const PartSeq &get_parts() const { return parts; } + const EndpointSeq &get_endpoints() const { return endpoints; } + const Endpoint *get_endpoint_by_link(Track *) const; + const std::string &get_description() const { return description; } + float get_slope() const { return slope; } + bool get_flex() const { return flex; } + float get_length() const; + float get_total_length() const; + unsigned get_turnout_id() const { return turnout_id; } + unsigned get_sensor_id() const { return sensor_id; } + unsigned get_n_routes() const; + bool snap_to(Track &, bool); + bool snap(Point &, float &) const; + void break_link(Track &); + void break_links(); + void check_slope(); + const Endpoint *traverse(const Endpoint *, unsigned) const; + + /** + Creates a copy of the track. The new track will be almost identical, but + won't have any links to other tracks, nor a turnout or sensor id. + */ + Track *copy() const; +private: + unsigned art_nr; + std::string description; + PartSeq parts; + EndpointSeq endpoints; + Point pos; + float rot; + float slope; + bool flex; + unsigned turnout_id; + unsigned sensor_id; + + // Direct copying not allowed due to links. See the copy() function. + //Track(const Track &); + Track &operator=(const Track &); + + void collect_endpoints(); +}; +typedef std::list TrackSeq; +typedef std::set TrackSet; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/trafficmanager.cpp b/source/libmarklin/trafficmanager.cpp new file mode 100644 index 0000000..7a47f14 --- /dev/null +++ b/source/libmarklin/trafficmanager.cpp @@ -0,0 +1,71 @@ +#include "control.h" +#include "layout.h" +#include "trafficmanager.h" +#include "turnout.h" + +using namespace std; + +namespace Marklin { + +TrafficManager::TrafficManager(Control &c, Layout &l): + control(c), + layout(l) +{ + const TrackSeq &tracks=layout.get_tracks(); + + TrackSet used_tracks; + for(TrackSeq::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + if(unsigned tid=(*i)->get_turnout_id()) + { + Turnout *t=control.get_turnout(tid); + if(!t) + t=new Turnout(control, tid); + //t->signal_route_changed.connect(sigc::mem_fun(*i, &Track::set_current_route)); + } + if(unsigned sid=(*i)->get_sensor_id()) + { + Sensor *s=control.get_sensor(sid); + if(!s) + s=new Sensor(control, sid); + } + if(used_tracks.count(*i)==0) + { + Section *sect=new Section(*this, *i); + sections.push_back(sect); + used_tracks.insert(sect->get_tracks().begin(), sect->get_tracks().end()); + } + } + + for(SectionSeq::iterator i=sections.begin(); i!=sections.end(); ++i) + { + for(SectionSeq::iterator j=i; j!=sections.end(); ++j) + if(j!=i) + (*i)->check_link(**j); + (*i)->print_debug(); + } +} + +Section *TrafficManager::get_section_by_track(const Track *t) const +{ + for(SectionSeq::const_iterator i=sections.begin(); i!=sections.end(); ++i) + { + const TrackSet &tracks=(*i)->get_tracks(); + if(tracks.count(const_cast(t))) + return *i; + } + + return 0; +} + +void TrafficManager::add_train(Train *t) +{ + if(find(trains.begin(), trains.end(), t)==trains.end()) + trains.push_back(t); +} + +void TrafficManager::turnout_route_changed(unsigned, Turnout *) +{ +} + +} // namespace Marklin diff --git a/source/libmarklin/trafficmanager.h b/source/libmarklin/trafficmanager.h new file mode 100644 index 0000000..11ecc95 --- /dev/null +++ b/source/libmarklin/trafficmanager.h @@ -0,0 +1,31 @@ +#ifndef LIBMARKLIN_TRAFFICMANAGER_H_ +#define LIBMARKLIN_TRAFFICMANAGER_H_ + +#include "section.h" +#include "train.h" + +namespace Marklin { + +class Control; +class Layout; +class Turnout; + +class TrafficManager +{ +public: + TrafficManager(Control &, Layout &); + Control &get_control() const { return control; } + Section *get_section_by_track(const Track *) const; + void add_train(Train *); +private: + Control &control; + Layout &layout; + SectionSeq sections; + TrainSeq trains; + + void turnout_route_changed(unsigned, Turnout *); +}; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp new file mode 100644 index 0000000..73b2823 --- /dev/null +++ b/source/libmarklin/train.cpp @@ -0,0 +1,121 @@ +#include "control.h" +#include "trafficmanager.h" +#include "train.h" + +namespace Marklin { + +Train::Train(TrafficManager &tm, Locomotive &l): + trfc_mgr(tm), + loco(l), + target_speed(0) +{ + trfc_mgr.add_train(this); + trfc_mgr.get_control().signal_sensor_event.connect(sigc::mem_fun(this, &Train::sensor_event)); +} + +void Train::set_speed(unsigned speed) +{ + target_speed=speed; + if(rsv_sections.empty() && !reserve_more()) + return; + loco.set_speed(speed); +} + +void Train::place(Section *sect, const Section::Endpoint *entry) +{ + for(SectRefSeq::iterator i=rsv_sections.begin(); i!=rsv_sections.end();) + { + i->section->reserve(0); + i=rsv_sections.erase(i); + } + + for(SectRefSeq::iterator i=cur_sections.begin(); i!=cur_sections.end();) + { + i->section->reserve(0); + i=cur_sections.erase(i); + } + + if(!sect->reserve(this)) + return; + + cur_sections.push_back(SectionRef(sect, entry)); +} + +bool Train::free_section(Section *sect) +{ + for(SectRefSeq::iterator i=rsv_sections.begin(); i!=rsv_sections.end(); ++i) + if(i->section==sect) + { + while(i!=rsv_sections.end()) + { + i->section->reserve(0); + i=rsv_sections.erase(i); + } + return true; + } + + return false; +} + +void Train::sensor_event(unsigned addr, bool state) +{ + if(state) + { + SectRefSeq::iterator i; + for(i=rsv_sections.begin(); i!=rsv_sections.end(); ++i) + if(i->section->get_sensor_id() && i->section->get_sensor_id()!=addr) + break; + cur_sections.splice(cur_sections.begin(), rsv_sections, rsv_sections.begin(), i); + + reserve_more(); + if(rsv_sections.empty()) + loco.set_speed(0); + } + else + { + SectRefSeq::iterator i; + for(i=cur_sections.begin(); i!=cur_sections.end(); ++i) + if(i->section->get_sensor_id()==addr) + break; + if(i!=cur_sections.end()) + { + ++i; + for(SectRefSeq::iterator j=cur_sections.begin(); j!=i; ++j) + j->section->reserve(0); + cur_sections.erase(cur_sections.begin(), i); + } + + reserve_more(); + } +} + +bool Train::reserve_more() +{ + SectionRef *last=0; + if(!rsv_sections.empty()) + last=&rsv_sections.back(); + else if(!cur_sections.empty()) + last=&cur_sections.back(); + if(!last) + return false; + + bool result=false; + unsigned size=rsv_sections.size(); + while(size<5) + { + const Section::Endpoint *exit=last->section->traverse(last->entry); + if(exit->link->reserve(this)) + { + rsv_sections.push_back(SectionRef(exit->link, exit->link->get_endpoint_by_link(last->section))); + last=&rsv_sections.back(); + ++size; + result=true; + } + else + break; + } + + return result; +} + +} // namespace Marklin diff --git a/source/libmarklin/train.h b/source/libmarklin/train.h new file mode 100644 index 0000000..363fb55 --- /dev/null +++ b/source/libmarklin/train.h @@ -0,0 +1,45 @@ +#ifndef LIBMARKLIN_TRAIN_H_ +#define LIBMARKLIN_TRAIN_H_ + +#include +#include "section.h" + +namespace Marklin { + +class Locomotive; +class TrafficManager; + +class Train: public sigc::trackable +{ +public: + Train(TrafficManager &, Locomotive &); + const std::string &get_name() const { return name; } + void set_speed(unsigned); + void place(Section *, const Section::Endpoint *); + bool free_section(Section *); + void tick(); +private: + struct SectionRef + { + Section *section; + const Section::Endpoint *entry; + + SectionRef(Section *s, const Section::Endpoint *e): section(s), entry(e) { } + }; + typedef std::list SectRefSeq; + + TrafficManager &trfc_mgr; + std::string name; + Locomotive &loco; + SectRefSeq cur_sections; + SectRefSeq rsv_sections; + unsigned target_speed; + + void sensor_event(unsigned, bool); + bool reserve_more(); +}; +typedef std::list TrainSeq; + +} // namespace Marklin + +#endif diff --git a/source/libmarklin/turnout.cpp b/source/libmarklin/turnout.cpp new file mode 100644 index 0000000..eca9ae2 --- /dev/null +++ b/source/libmarklin/turnout.cpp @@ -0,0 +1,77 @@ +#include +#include +#include +#include "command.h" +#include "control.h" +#include "turnout.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Turnout::Turnout(Control &c, unsigned a): + control(c), + addr(a), + route(0) +{ + control.add_turnout(this); + + control.signal_turnout_event.connect(sigc::mem_fun(this, &Turnout::turnout_event)); + + char cmd[3]; + cmd[0]=CMD_TURNOUT_STATUS; + cmd[1]=addr&0xFF; + cmd[2]=(addr>>8)&0xFF; + control.command(string(cmd,3)).signal_done.connect(sigc::mem_fun(this, &Turnout::status_reply)); +} + +void Turnout::set_route(unsigned r) +{ + route=r; + + command(true); + (new Time::Timer(200*Time::msec))->signal_timeout.connect(sigc::mem_fun(this, &Turnout::switch_timeout)); + + signal_route_changed.emit(route); +} + +void Turnout::command(bool on) +{ + char cmd[3]; + cmd[0]=CMD_TURNOUT; + cmd[1]=addr&0xFF; + cmd[2]=((addr>>8)&0x7); + if(on) + cmd[2]|=0x40; + if(route==0) + cmd[2]|=0x80; + control.command(string(cmd,3)); +} + +void Turnout::status_reply(Error err, const string &reply) +{ + if(err==ERR_NO_ERROR) + { + route=(reply[0]&4)?0:1; + signal_route_changed.emit(route); + } +} + +bool Turnout::switch_timeout() +{ + command(false); + + return false; +} + +void Turnout::turnout_event(unsigned a, bool r) +{ + if(a==addr && r!=route) + { + route=r; + signal_route_changed.emit(route); + } +} + +} // namespace Marklin diff --git a/source/libmarklin/turnout.h b/source/libmarklin/turnout.h new file mode 100644 index 0000000..edf1c03 --- /dev/null +++ b/source/libmarklin/turnout.h @@ -0,0 +1,38 @@ +#ifndef LIBMARKLIN_TURNOUT_H_ +#define LIBMARKLIN_TURNOUT_H_ + +#include +#include +#include +#include +#include "constants.h" + +namespace Marklin { + +class Control; + +class Turnout +{ +public: + sigc::signal signal_route_changed; + + Turnout(Control &, unsigned); + void set_route(unsigned); + unsigned get_address() const { return addr; } + unsigned get_route() const { return route; } +private: + Control &control; + unsigned addr; + unsigned route; + + void command(bool); + void status_reply(Error, const std::string &); + bool switch_timeout(); + void turnout_event(unsigned, bool); +}; +typedef std::list TurnoutSeq; +typedef std::map TurnoutMap; + +} // namespace Marklin + +#endif diff --git a/source/shoppinglist/main.cpp b/source/shoppinglist/main.cpp new file mode 100644 index 0000000..a87e2f8 --- /dev/null +++ b/source/shoppinglist/main.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace Msp; + +class ShoppingList +{ +public: + ShoppingList(int, char **); + void print(ostream &); +private: + class InventoryLoader: public Parser::Loader + { + public: + InventoryLoader(ShoppingList &); + private: + ShoppingList &sl; + + void track(unsigned, unsigned); + }; + + class LayoutLoader: public Parser::Loader + { + public: + LayoutLoader(ShoppingList &); + private: + ShoppingList &sl; + + void track(unsigned); + }; + + typedef map TrackMap; + + TrackMap inventory; + TrackMap layout; + + void load_inventory(const string &); + void load_layout(const string &); +}; + +int main(int argc, char **argv) +{ + ShoppingList sl(argc, argv); + sl.print(cout); + return 0; +} + +ShoppingList::ShoppingList(int argc, char **argv) +{ + string inv_fn="inventory"; + GetOpt getopt; + getopt.add_option('i', "inventory", inv_fn, GetOpt::REQUIRED_ARG); + getopt(argc,argv); + + load_inventory(inv_fn); + load_layout(getopt.get_args().front()); +} + +void ShoppingList::load_inventory(const string &fn) +{ + ifstream in(fn.c_str()); + Parser::Parser parser(in, fn); + InventoryLoader il(*this); + il.load(parser); +} + +void ShoppingList::load_layout(const string &fn) +{ + ifstream in(fn.c_str()); + Parser::Parser parser(in, fn); + LayoutLoader ll(*this); + ll.load(parser); +} + +void ShoppingList::print(ostream &out) +{ + out<<"// Need to get:\n"; + for(TrackMap::iterator i=layout.begin(); i!=layout.end(); ++i) + { + TrackMap::iterator j=inventory.find(i->first); + if(j!=inventory.end()) + { + if(j->secondsecond) + out<<"track "<first<<' '<second-j->second<<";\n"; + } + else + out<<"track "<first<<' '<second<<";\n"; + } + + out<<"// Pre-existing:\n"; + for(TrackMap::iterator i=layout.begin(); i!=layout.end(); ++i) + { + TrackMap::iterator j=inventory.find(i->first); + if(j!=inventory.end()) + out<<"track "<first<<' '<second,j->second)<<";\n"; + } + + out<<"// Unused:\n"; + for(TrackMap::iterator i=inventory.begin(); i!=inventory.end(); ++i) + { + TrackMap::iterator j=layout.find(i->first); + if(j!=layout.end()) + { + if(j->secondsecond) + out<<"track "<first<<' '<second-j->second<<";\n"; + } + else + out<<"track "<first<<' '<second<<";\n"; + } +} + +ShoppingList::InventoryLoader::InventoryLoader(ShoppingList &s): + sl(s) +{ + add("track", &InventoryLoader::track); +} + +void ShoppingList::InventoryLoader::track(unsigned part, unsigned count) +{ + sl.inventory[part]+=count; +} + +ShoppingList::LayoutLoader::LayoutLoader(ShoppingList &s): + sl(s) +{ + add("track", &LayoutLoader::track); + add("base"); +} + +void ShoppingList::LayoutLoader::track(unsigned part) +{ + ++sl.layout[part]; +} diff --git a/tracks.dat b/tracks.dat new file mode 100644 index 0000000..75d36d9 --- /dev/null +++ b/tracks.dat @@ -0,0 +1,425 @@ +// Straight + +track 24064 +{ + description "Straight, 64.3mm (R3-R4-R5)"; + part + { + length 64.3; + }; +}; + +track 24071 +{ + description "Straight, 70.3mm (for slim turnouts)"; + part + { + length 70.8; + }; +}; + +track 24077 +{ + description "Straight, 77.5mm (R1-R2-R3)"; + part + { + length 77.5; + }; +}; + +track 24094 +{ + description "Straight, 94.2mm"; + part + { + length 94.2; + }; +}; + +track 24172 +{ + description "Straight, 171.7mm"; + part + { + length 171.7; + }; +}; + +track 24188 +{ + description "Straight, 188.3mm (turnout length)"; + part + { + length 188.3; + }; +}; + +track 24229 +{ + description "Straight, 229.3mm"; + part + { + length 229.3; + }; +}; + +track 24236 +{ + description "Straight, 236.1mm (slim turnout length)"; + part + { + length 236.1; + }; +}; + +// Curves, R1 + +track 24107 +{ + description "Curve, R1 = 360mm, 7.5°"; + part + { + length 7.5; + radius 360; + }; +}; + +track 24115 +{ + description "Curve, R1 = 360mm, 15°"; + part + { + length 15; + radius 360; + }; +}; + +track 24130 +{ + description "Curve, R1 = 360mm, 30°"; + part + { + length 30; + radius 360; + }; +}; + +// Curves, R2 + +track 24206 +{ + description "Curve, R2 = 437.5mm, 5.7° (turnout to 30°)"; + part + { + length 5.7; + radius 437.5; + }; +}; + +track 24207 +{ + description "Curve, R2 = 437.5mm, 7.5°"; + part + { + length 7.5; + radius 437.5; + }; +}; + +track 24215 +{ + description "Curve, R2 = 437.5mm, 15°"; + part + { + length 15; + radius 437.5; + }; +}; + +track 24224 +{ + description "Curve, R2 = 437.5mm, 24.3° (turnout)"; + part + { + length 24.3; + radius 437.5; + }; +}; + +track 24230 +{ + description "Curve, R2 = 437.5mm, 30°"; + part + { + length 30; + radius 437.5; + }; +}; + +// Curves, R3 + +track 24330 +{ + description "Curve, R3 = 515mm, 30°"; + part + { + length 30; + radius 515; + }; +}; + +// Curves, R4 + +track 24430 +{ + description "Curve, R4 = 579.3mm, 30°"; + part + { + length 30; + radius 579.3; + }; +}; + +// Curves, R5 + +track 24530 +{ + description "Curve, R5 = 643.6mm, 30°"; + part + { + length 30; + radius 643.6; + }; +}; + +// Curves, slim turnout + +track 24912 +{ + description "Curve, R = 1114.6mm, 12.1° (slim turnout)"; + part + { + length 12.1; + radius 1114.6; + }; +}; + +// Curved turnouts, R1 + +track 24671 +{ + description "Curved turnout, left"; + part + { + length 77.5; + route 0; + }; + part + { + start 77.5 0 0; + length 30; + radius 360; + route 0; + }; + part + { + length 30; + radius 360; + route 1; + }; +}; + +track 24672 +{ + description "Curved turnout, right"; + part + { + length 77.5; + route 0; + }; + part + { + start 77.5 0 0; + length 30; + radius -360; + route 0; + }; + part + { + length 30; + radius -360; + route 1; + }; +}; + +// Turnouts, R2 + +track 24611 +{ + description "Turnout, left"; + part + { + length 188.3; + route 0; + }; + part + { + length 24.3; + radius 437.5; + route 1; + }; +}; + +track 24612 +{ + description "Turnout, right"; + part + { + length 188.3; + route 0; + }; + part + { + length 24.3; + radius -437.5; + route 1; + }; +}; + +track 24630 +{ + description "Turnout, 3-way"; + part + { + length 188.3; + route 0; + }; + part + { + length 24.3; + radius 437.5; + route 1; + }; + part + { + length 24.3; + radius -437.5; + route 2; + }; +}; + +track 24624 +{ + description "Turnout, double crossing"; + part + { + length 188.3; + }; + part + { + length 24.3; + radius -437.5; + }; + part + { + start 8.34 38.74 -24.3; + length 188.3; + }; + part + { + start 8.34 38.74 -24.3; + length 24.3; + radius 437.5; + }; +}; + +// Slim turnouts + +track 24711 +{ + description "Slim turnout, left"; + part + { + length 236.1; + route 0; + }; + part + { + length 12.1; + radius 1114.6; + route 1; + }; +}; + +track 24712 +{ + description "Slim turnout, right"; + part + { + length 236.1; + route 0; + }; + part + { + length 12.1; + radius -1114.6; + route 1; + }; +}; + +// Crossings + +track 24640 +{ + description "Crossing, 24.3°"; + part + { + length 188.3; + }; + part + { + start 8.34 38.74 -24.3; + length 188.3; + }; +}; + +track 24649 +{ + description "Crossing, 48.6°"; + part + { + length 103.3; + }; + part + { + start 17.49 38.74 -48.6; + length 103.3; + }; +}; + +track 24740 +{ + description "Slim crossing, 12.1°"; + part + { + length 236.1; + }; + part + { + start 2.62 24.75 -12.1; + length 236.1; + }; +}; + +// Specials + +track 24977 +{ + description "Bumper"; + part + { + length 94.2; + dead_end true; + }; +}; +