From 444c7efb2fadb10e98197a62b791829d821370c0 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 30 May 2009 19:14:17 +0000 Subject: [PATCH] Convert designer to use mspgltk for UI Add a toolbar to designer (not all buttons are functional yet) Support for defining routes for a layout --- Build | 1 + dejavu-20.font | 1341 ---------------------------------- dejavu-20.png | Bin 16508 -> 0 bytes gui.png | Bin 4468 -> 4513 bytes marklin.res | 28 +- source/designer/designer.cpp | 229 +++--- source/designer/designer.h | 38 +- source/designer/input.cpp | 108 +-- source/designer/input.h | 13 +- source/designer/toolbar.cpp | 100 +++ source/designer/toolbar.h | 29 + source/libmarklin/layout.cpp | 118 ++- source/libmarklin/layout.h | 12 +- source/libmarklin/route.cpp | 174 ++++- source/libmarklin/route.h | 33 +- 15 files changed, 673 insertions(+), 1551 deletions(-) delete mode 100644 dejavu-20.font delete mode 100644 dejavu-20.png create mode 100644 source/designer/toolbar.cpp create mode 100644 source/designer/toolbar.h diff --git a/Build b/Build index 7f0fb86..817d757 100644 --- a/Build +++ b/Build @@ -42,6 +42,7 @@ package "märklin" { source "source/designer"; require "mspstrings"; + require "mspgltk"; require "mspgbase"; build_info { diff --git a/dejavu-20.font b/dejavu-20.font deleted file mode 100644 index 98f1401..0000000 --- a/dejavu-20.font +++ /dev/null @@ -1,1341 +0,0 @@ -//texture "dejavu-20.png"; -default_size 20; -ascent 0.950; -descent -0.250; -glyph 32 -{ - texcoords 0.023438 0.925781 0.023438 0.925781; - size 0.000 0.000; - offset 0.000 0.000; - advance 0.300; -}; -glyph 33 -{ - texcoords 0.070312 0.925781 0.074219 0.984375; - size 0.100 0.750; - offset 0.150 0.000; - advance 0.400; -}; -glyph 34 -{ - texcoords 0.115234 0.964844 0.126953 0.984375; - size 0.300 0.250; - offset 0.100 0.500; - advance 0.500; -}; -glyph 35 -{ - texcoords 0.156250 0.925781 0.183594 0.984375; - size 0.700 0.750; - offset 0.100 0.000; - advance 0.850; -}; -glyph 36 -{ - texcoords 0.208984 0.914062 0.228516 0.984375; - size 0.500 0.900; - offset 0.100 -0.150; - advance 0.650; -}; -glyph 37 -{ - texcoords 0.251953 0.925781 0.285156 0.984375; - size 0.850 0.750; - offset 0.000 0.000; - advance 0.950; -}; -glyph 38 -{ - texcoords 0.302734 0.925781 0.330078 0.984375; - size 0.700 0.750; - offset 0.050 0.000; - advance 0.750; -}; -glyph 39 -{ - texcoords 0.363281 0.964844 0.367188 0.984375; - size 0.100 0.250; - offset 0.100 0.500; - advance 0.300; -}; -glyph 40 -{ - texcoords 0.410156 0.914062 0.417969 0.984375; - size 0.200 0.900; - offset 0.100 -0.150; - advance 0.400; -}; -glyph 41 -{ - texcoords 0.458984 0.914062 0.466797 0.984375; - size 0.200 0.900; - offset 0.100 -0.150; - advance 0.400; -}; -glyph 42 -{ - texcoords 0.503906 0.945312 0.521484 0.984375; - size 0.450 0.500; - offset 0.000 0.250; - advance 0.500; -}; -glyph 43 -{ - texcoords 0.548828 0.925781 0.572266 0.972656; - size 0.600 0.600; - offset 0.100 0.000; - advance 0.850; -}; -glyph 44 -{ - texcoords 0.607422 0.914062 0.613281 0.933594; - size 0.150 0.250; - offset 0.050 -0.150; - advance 0.300; -}; -glyph 45 -{ - texcoords 0.654297 0.945312 0.664062 0.953125; - size 0.250 0.100; - offset 0.050 0.250; - advance 0.350; -}; -glyph 46 -{ - texcoords 0.705078 0.925781 0.708984 0.933594; - size 0.100 0.100; - offset 0.100 0.000; - advance 0.300; -}; -glyph 47 -{ - texcoords 0.750000 0.921875 0.763672 0.984375; - size 0.350 0.800; - offset 0.000 -0.050; - advance 0.350; -}; -glyph 48 -{ - texcoords 0.794922 0.925781 0.814453 0.984375; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 49 -{ - texcoords 0.845703 0.925781 0.863281 0.984375; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 50 -{ - texcoords 0.892578 0.925781 0.912109 0.984375; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 51 -{ - texcoords 0.941406 0.925781 0.960938 0.984375; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 52 -{ - texcoords 0.013672 0.828125 0.035156 0.886719; - size 0.550 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 53 -{ - texcoords 0.064453 0.828125 0.082031 0.886719; - size 0.450 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 54 -{ - texcoords 0.111328 0.828125 0.130859 0.886719; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 55 -{ - texcoords 0.160156 0.828125 0.179688 0.886719; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 56 -{ - texcoords 0.208984 0.828125 0.228516 0.886719; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 57 -{ - texcoords 0.257812 0.828125 0.277344 0.886719; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 58 -{ - texcoords 0.314453 0.828125 0.318359 0.867188; - size 0.100 0.500; - offset 0.100 0.000; - advance 0.350; -}; -glyph 59 -{ - texcoords 0.363281 0.816406 0.369141 0.867188; - size 0.150 0.650; - offset 0.050 -0.150; - advance 0.350; -}; -glyph 60 -{ - texcoords 0.402344 0.832031 0.427734 0.875000; - size 0.650 0.550; - offset 0.100 0.050; - advance 0.850; -}; -glyph 61 -{ - texcoords 0.451172 0.839844 0.476562 0.863281; - size 0.650 0.300; - offset 0.100 0.150; - advance 0.850; -}; -glyph 62 -{ - texcoords 0.500000 0.832031 0.525391 0.875000; - size 0.650 0.550; - offset 0.100 0.050; - advance 0.850; -}; -glyph 63 -{ - texcoords 0.552734 0.828125 0.568359 0.886719; - size 0.400 0.750; - offset 0.050 0.000; - advance 0.550; -}; -glyph 64 -{ - texcoords 0.591797 0.816406 0.626953 0.886719; - size 0.900 0.900; - offset 0.050 -0.150; - advance 1.000; -}; -glyph 65 -{ - texcoords 0.646484 0.828125 0.671875 0.886719; - size 0.650 0.750; - offset 0.000 0.000; - advance 0.700; -}; -glyph 66 -{ - texcoords 0.697266 0.828125 0.716797 0.886719; - size 0.500 0.750; - offset 0.100 0.000; - advance 0.700; -}; -glyph 67 -{ - texcoords 0.744141 0.828125 0.767578 0.886719; - size 0.600 0.750; - offset 0.050 0.000; - advance 0.700; -}; -glyph 68 -{ - texcoords 0.792969 0.828125 0.816406 0.886719; - size 0.600 0.750; - offset 0.100 0.000; - advance 0.750; -}; -glyph 69 -{ - texcoords 0.845703 0.828125 0.863281 0.886719; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 70 -{ - texcoords 0.894531 0.828125 0.910156 0.886719; - size 0.400 0.750; - offset 0.100 0.000; - advance 0.600; -}; -glyph 71 -{ - texcoords 0.939453 0.828125 0.964844 0.886719; - size 0.650 0.750; - offset 0.050 0.000; - advance 0.800; -}; -glyph 72 -{ - texcoords 0.013672 0.730469 0.035156 0.789062; - size 0.550 0.750; - offset 0.100 0.000; - advance 0.750; -}; -glyph 73 -{ - texcoords 0.070312 0.730469 0.074219 0.789062; - size 0.100 0.750; - offset 0.100 0.000; - advance 0.300; -}; -glyph 74 -{ - texcoords 0.117188 0.714844 0.126953 0.789062; - size 0.250 0.950; - offset -0.050 -0.200; - advance 0.300; -}; -glyph 75 -{ - texcoords 0.158203 0.730469 0.181641 0.789062; - size 0.600 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 76 -{ - texcoords 0.210938 0.730469 0.228516 0.789062; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.550; -}; -glyph 77 -{ - texcoords 0.255859 0.730469 0.281250 0.789062; - size 0.650 0.750; - offset 0.100 0.000; - advance 0.850; -}; -glyph 78 -{ - texcoords 0.306641 0.730469 0.328125 0.789062; - size 0.550 0.750; - offset 0.100 0.000; - advance 0.750; -}; -glyph 79 -{ - texcoords 0.351562 0.730469 0.378906 0.789062; - size 0.700 0.750; - offset 0.050 0.000; - advance 0.800; -}; -glyph 80 -{ - texcoords 0.406250 0.730469 0.423828 0.789062; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.600; -}; -glyph 81 -{ - texcoords 0.449219 0.718750 0.476562 0.789062; - size 0.700 0.900; - offset 0.050 -0.150; - advance 0.800; -}; -glyph 82 -{ - texcoords 0.501953 0.730469 0.523438 0.789062; - size 0.550 0.750; - offset 0.100 0.000; - advance 0.700; -}; -glyph 83 -{ - texcoords 0.550781 0.730469 0.572266 0.789062; - size 0.550 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 84 -{ - texcoords 0.597656 0.730469 0.621094 0.789062; - size 0.600 0.750; - offset 0.000 0.000; - advance 0.600; -}; -glyph 85 -{ - texcoords 0.648438 0.730469 0.669922 0.789062; - size 0.550 0.750; - offset 0.100 0.000; - advance 0.750; -}; -glyph 86 -{ - texcoords 0.695312 0.730469 0.720703 0.789062; - size 0.650 0.750; - offset 0.000 0.000; - advance 0.700; -}; -glyph 87 -{ - texcoords 0.738281 0.730469 0.773438 0.789062; - size 0.900 0.750; - offset 0.050 0.000; - advance 1.000; -}; -glyph 88 -{ - texcoords 0.792969 0.730469 0.816406 0.789062; - size 0.600 0.750; - offset 0.050 0.000; - advance 0.700; -}; -glyph 89 -{ - texcoords 0.841797 0.730469 0.865234 0.789062; - size 0.600 0.750; - offset 0.000 0.000; - advance 0.600; -}; -glyph 90 -{ - texcoords 0.890625 0.730469 0.914062 0.789062; - size 0.600 0.750; - offset 0.050 0.000; - advance 0.700; -}; -glyph 91 -{ - texcoords 0.947266 0.718750 0.955078 0.789062; - size 0.200 0.900; - offset 0.100 -0.150; - advance 0.400; -}; -glyph 92 -{ - texcoords 0.017578 0.628906 0.031250 0.691406; - size 0.350 0.800; - offset 0.000 -0.050; - advance 0.350; -}; -glyph 93 -{ - texcoords 0.068359 0.621094 0.076172 0.691406; - size 0.200 0.900; - offset 0.100 -0.150; - advance 0.400; -}; -glyph 94 -{ - texcoords 0.109375 0.671875 0.134766 0.691406; - size 0.650 0.250; - offset 0.100 0.500; - advance 0.850; -}; -glyph 95 -{ - texcoords 0.160156 0.613281 0.179688 0.621094; - size 0.500 0.100; - offset 0.000 -0.250; - advance 0.500; -}; -glyph 96 -{ - texcoords 0.214844 0.679688 0.224609 0.695312; - size 0.250 0.200; - offset 0.050 0.600; - advance 0.500; -}; -glyph 97 -{ - texcoords 0.259766 0.632812 0.277344 0.675781; - size 0.450 0.550; - offset 0.050 0.000; - advance 0.600; -}; -glyph 98 -{ - texcoords 0.306641 0.632812 0.326172 0.691406; - size 0.500 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 99 -{ - texcoords 0.357422 0.632812 0.375000 0.675781; - size 0.450 0.550; - offset 0.050 0.000; - advance 0.550; -}; -glyph 100 -{ - texcoords 0.404297 0.632812 0.423828 0.691406; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.650; -}; -glyph 101 -{ - texcoords 0.453125 0.632812 0.472656 0.675781; - size 0.500 0.550; - offset 0.050 0.000; - advance 0.600; -}; -glyph 102 -{ - texcoords 0.505859 0.632812 0.519531 0.691406; - size 0.350 0.750; - offset 0.000 0.000; - advance 0.350; -}; -glyph 103 -{ - texcoords 0.550781 0.617188 0.570312 0.675781; - size 0.500 0.750; - offset 0.050 -0.200; - advance 0.650; -}; -glyph 104 -{ - texcoords 0.601562 0.632812 0.619141 0.691406; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 105 -{ - texcoords 0.656250 0.632812 0.660156 0.691406; - size 0.100 0.750; - offset 0.100 0.000; - advance 0.300; -}; -glyph 106 -{ - texcoords 0.703125 0.617188 0.710938 0.691406; - size 0.200 0.950; - offset 0.000 -0.200; - advance 0.300; -}; -glyph 107 -{ - texcoords 0.746094 0.632812 0.765625 0.691406; - size 0.500 0.750; - offset 0.100 0.000; - advance 0.600; -}; -glyph 108 -{ - texcoords 0.802734 0.632812 0.806641 0.691406; - size 0.100 0.750; - offset 0.100 0.000; - advance 0.300; -}; -glyph 109 -{ - texcoords 0.837891 0.632812 0.869141 0.675781; - size 0.800 0.550; - offset 0.100 0.000; - advance 1.000; -}; -glyph 110 -{ - texcoords 0.894531 0.632812 0.912109 0.675781; - size 0.450 0.550; - offset 0.100 0.000; - advance 0.650; -}; -glyph 111 -{ - texcoords 0.941406 0.632812 0.960938 0.675781; - size 0.500 0.550; - offset 0.050 0.000; - advance 0.600; -}; -glyph 112 -{ - texcoords 0.013672 0.519531 0.033203 0.578125; - size 0.500 0.750; - offset 0.100 -0.200; - advance 0.650; -}; -glyph 113 -{ - texcoords 0.062500 0.519531 0.082031 0.578125; - size 0.500 0.750; - offset 0.050 -0.200; - advance 0.650; -}; -glyph 114 -{ - texcoords 0.115234 0.535156 0.126953 0.578125; - size 0.300 0.550; - offset 0.100 0.000; - advance 0.400; -}; -glyph 115 -{ - texcoords 0.162109 0.535156 0.179688 0.578125; - size 0.450 0.550; - offset 0.050 0.000; - advance 0.500; -}; -glyph 116 -{ - texcoords 0.212891 0.535156 0.226562 0.589844; - size 0.350 0.700; - offset 0.050 0.000; - advance 0.400; -}; -glyph 117 -{ - texcoords 0.259766 0.535156 0.277344 0.578125; - size 0.450 0.550; - offset 0.100 0.000; - advance 0.650; -}; -glyph 118 -{ - texcoords 0.306641 0.535156 0.328125 0.578125; - size 0.550 0.550; - offset 0.000 0.000; - advance 0.550; -}; -glyph 119 -{ - texcoords 0.351562 0.535156 0.380859 0.578125; - size 0.750 0.550; - offset 0.050 0.000; - advance 0.850; -}; -glyph 120 -{ - texcoords 0.404297 0.535156 0.425781 0.578125; - size 0.550 0.550; - offset 0.000 0.000; - advance 0.550; -}; -glyph 121 -{ - texcoords 0.453125 0.519531 0.474609 0.578125; - size 0.550 0.750; - offset 0.000 -0.200; - advance 0.550; -}; -glyph 122 -{ - texcoords 0.503906 0.535156 0.521484 0.578125; - size 0.450 0.550; - offset 0.050 0.000; - advance 0.550; -}; -glyph 123 -{ - texcoords 0.552734 0.523438 0.568359 0.593750; - size 0.400 0.900; - offset 0.150 -0.150; - advance 0.650; -}; -glyph 124 -{ - texcoords 0.607422 0.515625 0.611328 0.593750; - size 0.100 1.000; - offset 0.150 -0.250; - advance 0.350; -}; -glyph 125 -{ - texcoords 0.650391 0.523438 0.666016 0.593750; - size 0.400 0.900; - offset 0.100 -0.150; - advance 0.650; -}; -glyph 126 -{ - texcoords 0.695312 0.550781 0.720703 0.570312; - size 0.650 0.250; - offset 0.100 0.200; - advance 0.850; -}; -glyph 160 -{ - texcoords 0.755859 0.535156 0.755859 0.535156; - size 0.000 0.000; - offset 0.000 0.000; - advance 0.300; -}; -glyph 161 -{ - texcoords 0.802734 0.535156 0.806641 0.593750; - size 0.100 0.750; - offset 0.150 0.000; - advance 0.400; -}; -glyph 162 -{ - texcoords 0.845703 0.523438 0.863281 0.589844; - size 0.450 0.850; - offset 0.100 -0.150; - advance 0.650; -}; -glyph 163 -{ - texcoords 0.894531 0.535156 0.912109 0.593750; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 164 -{ - texcoords 0.941406 0.539062 0.962891 0.582031; - size 0.550 0.550; - offset 0.000 0.050; - advance 0.650; -}; -glyph 165 -{ - texcoords 0.011719 0.437500 0.035156 0.496094; - size 0.600 0.750; - offset 0.000 0.000; - advance 0.650; -}; -glyph 166 -{ - texcoords 0.070312 0.425781 0.074219 0.492188; - size 0.100 0.850; - offset 0.150 -0.150; - advance 0.350; -}; -glyph 167 -{ - texcoords 0.113281 0.429688 0.128906 0.496094; - size 0.400 0.850; - offset 0.050 -0.100; - advance 0.500; -}; -glyph 168 -{ - texcoords 0.164062 0.488281 0.175781 0.496094; - size 0.300 0.100; - offset 0.100 0.650; - advance 0.500; -}; -glyph 169 -{ - texcoords 0.205078 0.437500 0.232422 0.496094; - size 0.700 0.750; - offset 0.150 0.000; - advance 1.000; -}; -glyph 170 -{ - texcoords 0.259766 0.457031 0.277344 0.496094; - size 0.450 0.500; - offset 0.050 0.250; - advance 0.450; -}; -glyph 171 -{ - texcoords 0.306641 0.441406 0.326172 0.476562; - size 0.500 0.450; - offset 0.100 0.050; - advance 0.600; -}; -glyph 172 -{ - texcoords 0.353516 0.445312 0.378906 0.468750; - size 0.650 0.300; - offset 0.100 0.100; - advance 0.850; -}; -glyph 173 -{ - texcoords 0.410156 0.457031 0.419922 0.464844; - size 0.250 0.100; - offset 0.050 0.250; - advance 0.350; -}; -glyph 174 -{ - texcoords 0.449219 0.437500 0.478516 0.496094; - size 0.750 0.750; - offset 0.150 0.000; - advance 1.000; -}; -glyph 175 -{ - texcoords 0.505859 0.488281 0.517578 0.496094; - size 0.300 0.100; - offset 0.100 0.650; - advance 0.500; -}; -glyph 176 -{ - texcoords 0.554688 0.472656 0.566406 0.496094; - size 0.300 0.300; - offset 0.100 0.450; - advance 0.500; -}; -glyph 177 -{ - texcoords 0.597656 0.437500 0.621094 0.488281; - size 0.600 0.650; - offset 0.150 0.000; - advance 0.850; -}; -glyph 178 -{ - texcoords 0.652344 0.464844 0.664062 0.496094; - size 0.300 0.400; - offset 0.050 0.350; - advance 0.400; -}; -glyph 179 -{ - texcoords 0.701172 0.464844 0.712891 0.496094; - size 0.300 0.400; - offset 0.050 0.350; - advance 0.400; -}; -glyph 180 -{ - texcoords 0.751953 0.484375 0.761719 0.500000; - size 0.250 0.200; - offset 0.150 0.600; - advance 0.500; -}; -glyph 181 -{ - texcoords 0.794922 0.421875 0.814453 0.480469; - size 0.500 0.750; - offset 0.100 -0.200; - advance 0.650; -}; -glyph 182 -{ - texcoords 0.845703 0.429688 0.863281 0.496094; - size 0.450 0.850; - offset 0.100 -0.100; - advance 0.650; -}; -glyph 183 -{ - texcoords 0.900391 0.460938 0.904297 0.468750; - size 0.100 0.100; - offset 0.100 0.300; - advance 0.300; -}; -glyph 184 -{ - texcoords 0.947266 0.421875 0.955078 0.437500; - size 0.200 0.200; - offset 0.150 -0.200; - advance 0.500; -}; -glyph 185 -{ - texcoords 0.019531 0.367188 0.029297 0.398438; - size 0.250 0.400; - offset 0.100 0.350; - advance 0.400; -}; -glyph 186 -{ - texcoords 0.064453 0.359375 0.080078 0.398438; - size 0.400 0.500; - offset 0.050 0.250; - advance 0.450; -}; -glyph 187 -{ - texcoords 0.111328 0.343750 0.130859 0.378906; - size 0.500 0.450; - offset 0.100 0.050; - advance 0.600; -}; -glyph 188 -{ - texcoords 0.154297 0.339844 0.185547 0.398438; - size 0.800 0.750; - offset 0.100 0.000; - advance 0.950; -}; -glyph 189 -{ - texcoords 0.203125 0.339844 0.234375 0.398438; - size 0.800 0.750; - offset 0.100 0.000; - advance 0.950; -}; -glyph 190 -{ - texcoords 0.251953 0.339844 0.285156 0.398438; - size 0.850 0.750; - offset 0.050 0.000; - advance 0.950; -}; -glyph 191 -{ - texcoords 0.308594 0.339844 0.324219 0.398438; - size 0.400 0.750; - offset 0.050 0.000; - advance 0.550; -}; -glyph 192 -{ - texcoords 0.353516 0.339844 0.378906 0.414062; - size 0.650 0.950; - offset 0.000 0.000; - advance 0.700; -}; -glyph 193 -{ - texcoords 0.402344 0.339844 0.427734 0.414062; - size 0.650 0.950; - offset 0.000 0.000; - advance 0.700; -}; -glyph 194 -{ - texcoords 0.451172 0.339844 0.476562 0.414062; - size 0.650 0.950; - offset 0.000 0.000; - advance 0.700; -}; -glyph 195 -{ - texcoords 0.500000 0.339844 0.525391 0.410156; - size 0.650 0.900; - offset 0.000 0.000; - advance 0.700; -}; -glyph 196 -{ - texcoords 0.548828 0.339844 0.574219 0.414062; - size 0.650 0.950; - offset 0.000 0.000; - advance 0.700; -}; -glyph 197 -{ - texcoords 0.597656 0.339844 0.623047 0.414062; - size 0.650 0.950; - offset 0.000 0.000; - advance 0.700; -}; -glyph 198 -{ - texcoords 0.640625 0.339844 0.675781 0.398438; - size 0.900 0.750; - offset 0.000 0.000; - advance 1.000; -}; -glyph 199 -{ - texcoords 0.695312 0.324219 0.718750 0.398438; - size 0.600 0.950; - offset 0.050 -0.200; - advance 0.700; -}; -glyph 200 -{ - texcoords 0.748047 0.339844 0.765625 0.414062; - size 0.450 0.950; - offset 0.100 0.000; - advance 0.650; -}; -glyph 201 -{ - texcoords 0.796875 0.339844 0.814453 0.414062; - size 0.450 0.950; - offset 0.100 0.000; - advance 0.650; -}; -glyph 202 -{ - texcoords 0.845703 0.339844 0.863281 0.414062; - size 0.450 0.950; - offset 0.100 0.000; - advance 0.650; -}; -glyph 203 -{ - texcoords 0.894531 0.339844 0.912109 0.414062; - size 0.450 0.950; - offset 0.100 0.000; - advance 0.650; -}; -glyph 204 -{ - texcoords 0.947266 0.339844 0.955078 0.414062; - size 0.200 0.950; - offset 0.050 0.000; - advance 0.300; -}; -glyph 205 -{ - texcoords 0.019531 0.242188 0.027344 0.316406; - size 0.200 0.950; - offset 0.100 0.000; - advance 0.300; -}; -glyph 206 -{ - texcoords 0.066406 0.242188 0.078125 0.316406; - size 0.300 0.950; - offset 0.000 0.000; - advance 0.300; -}; -glyph 207 -{ - texcoords 0.115234 0.242188 0.126953 0.316406; - size 0.300 0.950; - offset 0.000 0.000; - advance 0.300; -}; -glyph 208 -{ - texcoords 0.156250 0.242188 0.183594 0.300781; - size 0.700 0.750; - offset 0.000 0.000; - advance 0.750; -}; -glyph 209 -{ - texcoords 0.208984 0.242188 0.230469 0.312500; - size 0.550 0.900; - offset 0.100 0.000; - advance 0.750; -}; -glyph 210 -{ - texcoords 0.253906 0.242188 0.281250 0.316406; - size 0.700 0.950; - offset 0.050 0.000; - advance 0.800; -}; -glyph 211 -{ - texcoords 0.302734 0.242188 0.330078 0.316406; - size 0.700 0.950; - offset 0.050 0.000; - advance 0.800; -}; -glyph 212 -{ - texcoords 0.351562 0.242188 0.378906 0.316406; - size 0.700 0.950; - offset 0.050 0.000; - advance 0.800; -}; -glyph 213 -{ - texcoords 0.400391 0.242188 0.427734 0.312500; - size 0.700 0.900; - offset 0.050 0.000; - advance 0.800; -}; -glyph 214 -{ - texcoords 0.449219 0.242188 0.476562 0.316406; - size 0.700 0.950; - offset 0.050 0.000; - advance 0.800; -}; -glyph 215 -{ - texcoords 0.501953 0.246094 0.523438 0.289062; - size 0.550 0.550; - offset 0.150 0.050; - advance 0.850; -}; -glyph 216 -{ - texcoords 0.544922 0.238281 0.576172 0.304688; - size 0.800 0.850; - offset 0.000 -0.050; - advance 0.800; -}; -glyph 217 -{ - texcoords 0.599609 0.242188 0.621094 0.316406; - size 0.550 0.950; - offset 0.100 0.000; - advance 0.750; -}; -glyph 218 -{ - texcoords 0.648438 0.242188 0.669922 0.316406; - size 0.550 0.950; - offset 0.100 0.000; - advance 0.750; -}; -glyph 219 -{ - texcoords 0.697266 0.242188 0.718750 0.316406; - size 0.550 0.950; - offset 0.100 0.000; - advance 0.750; -}; -glyph 220 -{ - texcoords 0.746094 0.242188 0.767578 0.316406; - size 0.550 0.950; - offset 0.100 0.000; - advance 0.750; -}; -glyph 221 -{ - texcoords 0.792969 0.242188 0.816406 0.316406; - size 0.600 0.950; - offset 0.000 0.000; - advance 0.600; -}; -glyph 222 -{ - texcoords 0.845703 0.242188 0.863281 0.300781; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.600; -}; -glyph 223 -{ - texcoords 0.892578 0.242188 0.912109 0.300781; - size 0.500 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 224 -{ - texcoords 0.943359 0.242188 0.960938 0.304688; - size 0.450 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 225 -{ - texcoords 0.015625 0.144531 0.033203 0.207031; - size 0.450 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 226 -{ - texcoords 0.064453 0.144531 0.082031 0.207031; - size 0.450 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 227 -{ - texcoords 0.113281 0.144531 0.130859 0.207031; - size 0.450 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 228 -{ - texcoords 0.162109 0.144531 0.179688 0.203125; - size 0.450 0.750; - offset 0.050 0.000; - advance 0.600; -}; -glyph 229 -{ - texcoords 0.210938 0.144531 0.228516 0.210938; - size 0.450 0.850; - offset 0.050 0.000; - advance 0.600; -}; -glyph 230 -{ - texcoords 0.251953 0.144531 0.285156 0.187500; - size 0.850 0.550; - offset 0.050 0.000; - advance 0.950; -}; -glyph 231 -{ - texcoords 0.308594 0.128906 0.326172 0.187500; - size 0.450 0.750; - offset 0.050 -0.200; - advance 0.550; -}; -glyph 232 -{ - texcoords 0.355469 0.144531 0.375000 0.207031; - size 0.500 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 233 -{ - texcoords 0.404297 0.144531 0.423828 0.207031; - size 0.500 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 234 -{ - texcoords 0.453125 0.144531 0.472656 0.207031; - size 0.500 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 235 -{ - texcoords 0.501953 0.144531 0.521484 0.203125; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.600; -}; -glyph 236 -{ - texcoords 0.556641 0.144531 0.566406 0.207031; - size 0.250 0.800; - offset -0.050 0.000; - advance 0.300; -}; -glyph 237 -{ - texcoords 0.605469 0.144531 0.615234 0.207031; - size 0.250 0.800; - offset 0.050 0.000; - advance 0.300; -}; -glyph 238 -{ - texcoords 0.652344 0.144531 0.664062 0.207031; - size 0.300 0.800; - offset 0.000 0.000; - advance 0.300; -}; -glyph 239 -{ - texcoords 0.701172 0.144531 0.712891 0.203125; - size 0.300 0.750; - offset 0.000 0.000; - advance 0.300; -}; -glyph 240 -{ - texcoords 0.746094 0.144531 0.765625 0.203125; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.600; -}; -glyph 241 -{ - texcoords 0.796875 0.144531 0.814453 0.207031; - size 0.450 0.800; - offset 0.100 0.000; - advance 0.650; -}; -glyph 242 -{ - texcoords 0.843750 0.144531 0.863281 0.207031; - size 0.500 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 243 -{ - texcoords 0.892578 0.144531 0.912109 0.207031; - size 0.500 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 244 -{ - texcoords 0.941406 0.144531 0.960938 0.207031; - size 0.500 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 245 -{ - texcoords 0.013672 0.046875 0.033203 0.109375; - size 0.500 0.800; - offset 0.050 0.000; - advance 0.600; -}; -glyph 246 -{ - texcoords 0.062500 0.046875 0.082031 0.105469; - size 0.500 0.750; - offset 0.050 0.000; - advance 0.600; -}; -glyph 247 -{ - texcoords 0.109375 0.050781 0.132812 0.089844; - size 0.600 0.500; - offset 0.100 0.050; - advance 0.850; -}; -glyph 248 -{ - texcoords 0.158203 0.042969 0.181641 0.093750; - size 0.600 0.650; - offset 0.000 -0.050; - advance 0.600; -}; -glyph 249 -{ - texcoords 0.210938 0.046875 0.228516 0.109375; - size 0.450 0.800; - offset 0.100 0.000; - advance 0.650; -}; -glyph 250 -{ - texcoords 0.259766 0.046875 0.277344 0.109375; - size 0.450 0.800; - offset 0.100 0.000; - advance 0.650; -}; -glyph 251 -{ - texcoords 0.308594 0.046875 0.326172 0.109375; - size 0.450 0.800; - offset 0.100 0.000; - advance 0.650; -}; -glyph 252 -{ - texcoords 0.357422 0.046875 0.375000 0.105469; - size 0.450 0.750; - offset 0.100 0.000; - advance 0.650; -}; -glyph 253 -{ - texcoords 0.404297 0.031250 0.425781 0.109375; - size 0.550 1.000; - offset 0.000 -0.200; - advance 0.550; -}; -glyph 254 -{ - texcoords 0.453125 0.031250 0.472656 0.105469; - size 0.500 0.950; - offset 0.100 -0.200; - advance 0.650; -}; -glyph 255 -{ - texcoords 0.501953 0.031250 0.523438 0.105469; - size 0.550 0.950; - offset 0.000 -0.200; - advance 0.550; -}; diff --git a/dejavu-20.png b/dejavu-20.png deleted file mode 100644 index c5d3c57dc4aac91a0b410d9551e2e425f3d27b07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16508 zcmZ|1byyrt^DaD#yM*8#+}$MvU)kBRRYfnVPXDtIb?T<(#&S5W@g^Mg)nG5bE(-B~lIwo}tniR@~( zU#7P3gQ3t)e?)xeCvw35VZ`(S1dWI%kv@h28Z(rT?APmAu>|!Jxeb$I&(e3yUP?J9 zXQfp2-_I+uc5~hK$h8=eAL~d2eKT5B?m=68i+WbkIldNhWMfGehxNE9+Z6wGhSqTo zUvNq`NajVV&OYqYXj=yJ2+>is;_xSS3y;ZZnGBENAmidMU%Abg>d+6Ba2NTG{k{or zh^Sg=paDZ(8=g~eMg;i^ABl0$x1h2tV~3Zq-k6W znS30`g|-zq*60p>V8siB51$V%z1a`4C1IjGFU!`#d#tJ0Au~T)?g)kn0p&x8y(j0o z9KLjjIcwLnI>3&>XiiPKmxI1b-xV+@@+S;Jvua}qH$FJ)sY7dH z5NOlyg*;)?&w+Z83%*eAI5na!o4n)5c_&^uh`6LgK7aF>Zg_{zNZA`3RaA2t6kSr3 zz{4xt@ln2ovthK-YwH~qEA~%;w#PDuV|kE8ZkNR_3<6?ZVpIcrhyHP!TZAQjjx|`C z!$%`T2m3B-9N;h!DN2AVxa}uO^PxrB_K!@^4pwUWpDo@3l$A2PA-Nma^ZI6vxBN>w zT_9LpIA*i_KHHrZ@(iXRSR>vUV)Sf6T_IEg$A1Rrfnls6a11^;eDu71OQGze`d699 zE6F1RPhPJMbCIs%91XllbN0@*v{+oEjJSDrP&`UBkz2e**xP#jL^RP#ckSVWnlb7N z_Hdgt%aNJSVJRn|T{RZ+H1b<|-HXCv+7cQSe-d3lbY_$(QV{4TR zj^%rQvGxLCnm;b~B0xN${UpbgFZhRQQ_g7Or%*dDNwn{LW4~ij_c=2!s4kdLAyM2i zk(&@p+oKn``rLVE_-girfKSAvNf5rPa7s3P7^um<{BK5=jdwitonmd|HN(Lz2+E+! z^$120rvmc!Ya^c6e4F^fa?}tK=%9Y}2=t$tMcx}DYdM3E z8ql?x`f{l^dna0`$^dmVPx})Fs7n5VH!H0k5y-N1t-=qbzU)p;S6}HngL14!p>}ea z@aDUUh^yo>vLTjd){3x%!vLZpuyp1%wIQKiZb<|Uk48f+=iMlVJB?@KcMp_H|MtEc zWC(R^5;uJ#ugcutxt&>+%?h`i^M*4jY8JkwySL_c`f-pMiw&Jr0*yZyQCtnMtQCnn>|EMkt5!jG~l{A(Mewv^8E3S2&Li2-3tKEO1`PQs= zni#+(JXn-~_SUTZ>Q8g9;xg9jVM~|-W}@lR!5jz7=G;H@yT^5voj~1kfonmIcJk+C z@7(;%-n|;kJkN7aMS-^u+Btr^$pY#AdZ{gmo5&v;e>~j{Yu0ix-%M*{Txk|s{pj=V=n zBKDf&%B)gLv8&BpR6-DKnF)B*v|KB%^GFR2WZhTkDeqvMw~AfHmX6u-)#GZBO3|xf z^UM+?(#xbk>zzR(Cj`|jTMKU0zmWNgH)#~3)GU5{d{1g(QlMtfBNcBS#MCS#t zUelgF;d4~&(6UV=N*-YMR#bidN756hBhIM0_H`!aIEKS6j z37afj8{pD08g55zXRz6w_L-gYK4_UnsQBLJ81R_KCqjxwmwQUOg9)*Xz5qEsZk47OGK2TDV?3C;?AB`pnCrUh9xnI&2&_^63s=$ z$Q$_WhyljW4UuvVoZ}&;qfP*H@yfxiE%t8BWP^XJ!?H-qVyBMusI{ z0wN>gn{IUUjfG*dhdU?hs2lg$(QwF%j~C|GEUnd3ATuD{-u#E@f*|xOf+FiwQ9b%O z@@%InMz-_p^2&ZU8}80yjcq3^v{pmaR2BA}+@AB-EJloamw~BWYe-v9M>GMF|88YV zyELHl{Tn@9Ivg`SI(jXkoxUDt?KgmH-LOKR>z5X>LhtNT%Cmg{?!&0HSV zGG#Usfmj_f-0Y-V>h299owLHfKr7h5KJJ-)<65y)2oOdQwzQ>ucgcHK%$&UPjTV^5 z&khr|`_knUZn+VgsvJCS*is8i>w*<)Gtj31SL?Joc0Eg zd#LmD%C~Uibe7QzjQ$fxVe?MpcaF-yj}p#Sed+cQ`^K z9+HO4GiC6N;B&oZ^I%9E7uPfWYWOaic*eJsIDdnZD#MYB4@(gg%)mBjt8ftZ(he)C zRivBmw0NphFn=6VE(7%$E7;}wxxWZt=N-BP^9{eiwwMQPA4_7}w}Ffx$%50F+J#9x8~gJ6X5@QANC|QW zd^I&cP7_=GnCI9`6pQe=>^7%rlwUc1S>c`zLnOU`^ zowBV*rh=dQZ6t|Vtx?Z$cr~H(aTrs4^f%b4Onv1}@$D(G*r>!ElbXFa(IlcGs2V<` z3(2D*6R5wCx^o#YErKxd6&EZ7Q{p8 z$+j-TYRz#t_6HvPAeslit>n@hOHr2+rZU*SyO@kR-)f$bS4>v#7v!;s`P=XujYxbT z$ECkn*}u`eXb^_NNFs;25w%1$f90YEUp*pR+|OLqv`@EbKW&7FJ}ck`Bpojw;zD9^ z^@ln~Mzoql5FxV;1?yVvTOkiVH#v=;SAKgnDfAYig5+Xps{*4NU9qgLM;6^c?3<0h zD$b7A^a+Q4=Dux1eHOrKO)wu@qsH)w}rXAo`z?=6nWQ>3%z+b#{$ z7*V}@_^JB{BCc5avIMIhIhhJ^Pv>bd4*KJb?J`7k~VPE zPlNY|y0-_buMDsfD8;#dVAu(J8#BMe{zs~N?$GlszzQGeF-s_Y>i;C(zf=ZeO>A2W zH=KolXl_KW9{H&pX1}8TMxGM(o%`)zx76Rz%sUXp-S3d!>Od0JzTu9qB>Su{)-UPQ zK=bX;30K!g_Ni}qFD_Mxi?MDn+2#%8W_}xKay#|^iuB44ffN}fXcAYrSO{CsB=`%u zkq#!1=IUVd3v7Rd>=coGJi>6`nD7>bdB_pPAU>B$m2u}*v>k-6M%dzLRL^>oU8Owj z2b@picaL^J=VnB^LZp(fSZnC5K)+m76Oa0*G*pRr+BP%QDigO5G~?ynoVBXf=qWbJ}#D9oYwr~-ACrUO@RC`_ge zZoxWvT@FWCp6=NFz+kk$m|%g9gY$x^%}UHH%!irovcg-emd7ewzE5{gkZaTjM;SQj zB=3mRHfC@hy5x;7D78$$AP``J{m9HQN|HGvhGWRM$%YAdRfo`=xE==jy^^!lhz~gC z*sNYeV^DU`Gi4mlhVTo9KV4cP@I)8nNMA**+P&qpqDIr_7 zd8uW*oe}8N8Wa@oU1+fveFjwUy=ASdtT7ITf7PTl%P*uJ3HH|+W+Pv~iW!>3Iq|Z} z=8)1a5DKdIET~#Of~jsA8Bf+|$P@oP`Px1RfCB!{0XY2sJ`Mj@L)rllYnX<&cZ$MP z7x7C~r&FFrEf7*WRlevM;Um@GLUELz(k)8W;=P}{el)aXoHyvn?}-(Wz}2hXJ$8b+ zta+EaCP&GK+$VWz0-h-0iIRFPh8afC9|I))+TaZ^9~@Qc{C$aozy7)$ylsE9NpK z_LLPChI>Q`G3-h4lSu}QgAw^DN=DDrtVtp9?JLb*^*@+Y)0GXuhK4uxYcBFcw#pmpOnodxU#iQW*o=-LRdB|Dm$e`iXiq@Kc=`Q%o~MVN=^ zAe&kEm5aDfweUNd3Dvr8e9GwXsnydv=~l0mv)fbMML}i2#gOP3^pJV%Fo+M}7_1?g zB~ew_y1m#318go7leThfxpaVm`AR$th6Rz+w!~0d!YQ%f51HC74wUpgLA}55R-^nFgkc+ zDLv@p!IVQqGy|Gq9rjb8t_IJMC5$Jn%r+F@FCrY8+mp{F;ttBr{>-C|N#qCM0m&Ma zVDV_k0E-~)NQ{)+;U9D2;O?BZ9U{rgm>5WK(maDf?@C&83q2n)&l*XsDJA}BFmdE9 z5TzE$Z%>GZu(hXI*(A-XwASUQgN{a6VEV-i_>Wz{9bIfIoGMV^Ub|tPx zVuN@z8MvUpGI5d9k6Ut*fj?;e&|H#@vPK982|!XI5(rB=+Lq~dqyGim6Wtem`JRVO z*LwN-j+{YaYl}1y60&H7z}7%JT>6gA-%LsHz?BYa0UCB4pv?v6O-ktnXwiv)*$}nd z5LCvT5JZl^gdksc0?=4BjJ02?Np3516)g09Fk_KFbn6+}E}l}y!vcwYttEEHcpD~{ zuU-It@9nHG*~3yhxnIIF3PnS##p2U9ysOm|Rj7V#5f85S&^t@H=dBgHPS>LO$a66Y zFwrb#@HLhhYdyK&8zqI0*iJrl#O&zhFrNss^Ec3+zp+6L@yt`E@uAAKx9F$COO%&H z6;aI@d>DX=t*+vTJkXBy@a7WNCD@+0ulFuL5yi{3r6bN8T)qynk9kyuf}Uls1Rw*v ziI&6BL)6O(y}Oy-xc=kpQ+(y{noWF0+?yR!l6!4Q%rq;La7kai0Nw;;SYE&o2`{pv zZ*VFBnBbnuTlta)dJssaTvZ?gEj1Q31TG;0U8fI5Fk+~mEA}X0-p+5d#9kO1$C22L z-t4CpxOA1*{eDZaDpkfutW?ca9pz79{tjH;+MdhKGdvMpDs&HL;$`#OIx*#q06}^f zKj{OxcnnRt%bj+9n*Fb;@?18~ge`!?u8$wKe9s$IdJG2AW;IU?oWobP(>wNKFa2S= z5ZWC#X?o2HS;DOhO9k220wEw5WU8OJ8hj10o(L~LC-k9a`)?gt_%pM9zkz%R&%Qx` z9GjUvC3UCkP!7V`^cRJ)jsFD+gZ)gR<+aAetwQfcUBd$!PCBqeRwQp16$F_>2YM1F zkbpjGK=YYK@l~uSO|v~BL9^=1^4}d%Yj&D*&^%(>6)x|Ktb=)DLRh#0;(03pA7yP{ z4^eV}vm6B@tOwVI{1n`Hl&IW=so|AdVIC|U7d$@#WgJZ4caI$|eB!?V-j%b7mIk<1 zseF~Ij1sIc#mDLA|l~;-oa$h9%;{O6)DItl|C6_zOe04#&~c`0rj@4E{>`EaATCkQ8fMg5zSSId zDlHo0omkkebBpb?_JDxfWP7X3XB9(4$YDFacAR6!7feulKg3cr^zv_RHtx%EYC*hQ zqF)Op8+*LlSjKSlsX4p!-F_$EG*{Y{N}Zp+{sYrRY;>4k#)ux{>OlO4yuSJNsqcJV zLv=w2PmH1(CWjU+kc4(a2JhlO)TsOy))!Os zVDsHH1i_)>+Z(@VX|sL@FlPAd%0U8J;naNCqA4}CFvpyL!-Bpn1@E+6qcTFvm{bG z*4;O!AslJS+k0XvlN(#qPeQI1C>+yTJvsE8F3#0y?}l*pUY{Me-W-Hmw;NpdljjyA z=g*utY2`AH0bj{zF1qiDCW~sA*0JK5-GEKGUyJNPW|h#w%*%wmHUdt z4dlMcOwqfV_1H^$LHI~xFk>7x2;_83?{Yqpk@I_OvlH$66|Ut;$&crD>5uH2N8FuA zlR&UBw2X^pue>xe+`jpqWuQ3}8q2W&1!!7;Cdn>A3ou;jQEe2x7DP2M%=qW9G#N`) z?{?uN-=a09fUSn!LU{;gn((GARNfXWkDv~Nkb)XV0SHSe6E&jKT~$Q?@xdTYQ@3Lu z8iqk75Mx4F&5MG53h&|D4#J0#LMx_WA(U*mJgQIp!(GZ{9;~c(o+3h5eou!71l7xY zW&x_LfY_sf2&kPF7lhVh&pbr8Se-}f2Mi5bDNRj#2@OI~wRsk< z&jZJ1wCWzxTT2}5jDAeHss}m#w$mk9bB0o_w5uaUPSb|X>Saa|^@n|hM%sroc_P*P z;mbk7XTB1Imzvs}t<|6TM(}upxdUrNyckO^q-o-Z6B?j9%jU2v=8;ZsAwPY}2iD z%->PJPsK2rVM{0)1#-)_ohZ2F1&lEPl^TID=zMjId%~l9>r97F(_2+5OOuX10+k8^ zyPy6t_v9d;j{0V2zYfoHAMunxAYP~)tZnm|hvZ%!T_^DUkDv_Pr>!cT5OH@WYNHjEE?ry z8_;qoYGP%I4{kf=OOX?t`=b8B|APelzT;Rqv6_tMg}}1^d+>|}Sb~|^yH7b$DZV-< z!^-|>u*FyIH&MX{&$AJ&9Xf&d*lS#2r-?5Y=R3+!yEGW=yL+h&X8GWP<^tpwU8@;l zh#A6c2wp+Q#kGMWTpkQs5nb4jGUyvGYsmn#iV6v9$Mr6sGIk}UPnw~z|Ak||n_%VJ zU~@ivnu>+L%;}(3=MO-VOc@qbtI!Z;A)++ZMq0JgRM^*COp~T6S3lK|K>f6DpwKwB zjxI+#u2N}wH9%^%4a?4O=$&-n2NW^)yjdPhMgYH5qz!nv>$j7k~$ zj)Te~Q=VsUe?mbaFl_CFgG~BnIX zD2zIj^q*kn(L0iUCpSQXhF^zEz*NH!yYI%w=ZyiT$YNzR`G_NS5!v%h z8jht!Rq79ZzLjh$)_0}@!n{B9@?YccOhf-3QMafDw=O&Ss?0@pdeMhS6TSQ0LaUHa z*}Rkc`OQOlTcoJN){?I0cNs-EkuKf%g$D9lxC%Ms)LOc!4+C93m#S&}(!XrODw|ce zf4b$UFQ4;6w0;`? zxcN`RTLx96(pb~tQf287#LBo-=c~ce-JWW-F!br?r<*9=a-F~G+c$)x=Vid3@zJBf z`2@^(MVVEr_)yGAYmcxL?G});3?5##2)AY|mA$Rd=NBe`e9JYl*nZ)iVuW?B-cKSh zU1`Z}jl`pT{6_T2t5q<@Tyt3pI@AJ(_A+PA z2`l|nW_1A8(jaT0ymtB~DdmE}v`x)r&w^M$kz(ZxXHSuNEP*6*##6El3t8YB)m4|N zw_vXo|AHPGaI6MxGj(%-a=~w8-DxD280t;Cx-ju+>f2)>?3B$zwF2iP&b=Nx$8ea@ zm`#_!f~yDro^ z-`UV*AAkGaWog}rkyY2@NYH9*Y78IaSseuP%u{gZ4qZfYwHYZg#4r&naO(bl5_0 z;x!-Qve!QS_SHjbWs32UkZx87R#?{h%C;X|8`a#6Ug!weC^BezAlG=7e14-xw;+n@ zO-$*8Fa(oEHGq_u=4vzjZijH732L_de2cCNBEi!WLeLRc-bg?G-&}y;OM+}^h+G`+ zoFjTNL7RhMWrG?DSbEVg(;1$xq1wEr!HJv#+J6e;&<}h%#x{~3Gk47QwmSQ4xRO?j zv@Wn+=%)|aXTh*w`(#553=l)#i;sT<>gZ-2A5+)`s#SSW0q=cYEOop2hl{G>l)my*7j)D%8fZseL$q;R;MGN zgHpi0N~U9XY}h>vVJb@9s2p#t>|-C)L)~P$<(pLHA}uY*H0O^^42)S8KP#r9AuY+d zi5Q|=B%?cWIjhDXqC3LzoXPXBvGH?@nPmiD--IV6cMe}GQ z_Lq0ex~FOU4P}q_{$0&RpmgaOJKJFfe}oD4g|?i$*KVI@fdve;~mQ(s2;gTaKVi^%TBY?OAeGumyxS?@L-sBUJI zXaDL$>X}o{iV?^IwPDWu1DrExD|!RwhVNjI%P+v<3}NCBs3hbo;Q^3l-;{GN)BtG$ z?q$_sBgih91rh5w`RQj2rHsuO|)FX)#WHXO+qQ$Rm?Ag;MonyR!CSL~QW zn{+445ZFoD2V)4Qs|_1a*-DsBF+*+I4ILs5kP(LsyYeLb+8ZKvkp+|Vn1c{^re@Yk zAnPOnT!HYp=ruj43S5;I>yar?gMPHjs>ra_hb1kb-h3f^#m6)6;O9~(@jk9ov|ew< z-}K*j)6I_m3UK&%($@|3XIvTJGjN!&8!MV9+gMram?+JbLMwr$&quaE^@s?6k|9C! zBJ_S-8SEsm!U1;`xZe^_!5|yM^eX8>0a!^gGqaJhbLEI@&<&J z0s1s+sokZXQ%uY^Pb|=-UXfqDL3zmhT6q<+>$d88HOyN0hBeyFgXyLpJ-FuwiAo2L z5Bu5_;Oz3zo*st&60s9=sF2J1vP_oszJ~QlYuTlrh#Y6x!RB*wzMB;NN`EtrVIQ@D zTk<|by~_Ge({e>Y^8QAKo@l@{O&VWBn!Wks#R zY&Wh%r@YHtdZfO@vuLJ@>e9rUHH3_s6{RPvExfJ4V>eY!>R$_tGa_INib(Kq9U&p=Zs^si4QUW-))_+!fjKO zU8J^Q{Hw846dqy{5^u|$51J3=ipgqRZ+T&`G{|J_s@=trcH z%iFyvljdkU-6d?<*N6#B5>C2|CsVL= zeEOxnvF-gQ>$bEx5FX$F5sVnSC?lqN+a$_U<(7t6PV5hGdmJ+O;8SS9CEGq-|F_^hr&P4#ff zxRGy#7WZfXg-T@*MNA2EtlOHGP2xBg)U(-&ra_5<)q!Ivb3b3K_!ApBjS9?~U*_F*YOCCYjwMI+gU)={2Qjwg*Kegs~L%VV}btI7vKtRFq0|->nD605H{N7MX9Ne35}Y z_EK*ophB4QjokBOO)#Tg$>b>`(&Xqb6bCuilc-u?O@C6mYuvUP#n3Hp$Zq+Kojwkr zz_T1is|C91$Ua{9LV9w8LeWX*c_wlE+;*hMr&Ngvf{yRnvb6!dGYKZ;x*2;*bS@}; z5o~Evj=!ey!9HvQH|vgD-Jd@sl#CmA;K(z=LfchR`sxpL7$t)5nvF}rhsOe?3+$r{i(LcvfmfVSAkMPD4|9nVX>oNMytre!!KCg48 z7tEJX>{g6;>8X(=RG;C~EEy9ISJj!~fCTK)y(vX@$vHg^;*w1CTnMyrxcO*>_R9J) z5L}m2$8*CgB&N~<3(WJQx;CEp0e6k~sO@ari1m;skqND`yJUI`!DXoyA9(geN(JTL z8dZFw;Q&@(-PLp;up%f;HXU51Ys4oI%9D-Na-gH-CQHQJvR^f#4yh9sftNjFn9V7P z6IA@rkw|0fjl<3dzk}md40*{wHc@F?8Lj=pCqb<%a~3hQ-o zWa66nM`ZKLX!Si1`g6+T>#l>Ks;tb^cc#+C-$!{!o+4UXzE_?jPrA=GtEle*NibD7 zY~pr{zEhjLC7mcjZA>UG~DOk;pf?XwBu<9 zm47F(z=ldlh@6>fbI@!aMoiJ1uVA!S?w{DRZff+`5lsCznnf5|1jg<%@G&y?^40$prQ{-96rK;j zPSg;FZ`WV8Ddx40-kRZQWqYSnq{4PYTcaRQBzK_qYgR6I(Ow0gURk!2;s?PG@EXZu zuTX8`&GN{)yHZsAiAV1hkAX~i3(BH&kH@F4eD&sYUI8ZF5{WiuL{gtge!u9~5Aq@q z4)FX~BaKl)rRq!%MW)MitbKVU;jq&U6TBkgtO#0!{srxb^$CaRaZY?=!Pl`pn4e#q zt*khOuM>H!)?_&*sm3Q6uD<(TIcc)pTi_bbK_gjdO~;U5CkMTUNu7^8fPN4d*aoh1QUP`u~j-$*u_2rP2x)WqSIi@DesKHu5C++Ai`(<$tC@!Am8@HO~q zxI2kcdvAtpmKZAskeB2sl7nl7fDa2hYqJ9{O)H+w{;^bbdP~ml7`xm9q;>(5r3ns& z{7AE}y!|amJH;9g#uH~6FGBN3^%XErh+jc(R|1w%YvO-c za-A-(>YBO&E=Vlk{^YX!4P(! z{KfmHd>}mNUoSwV3e+?Cst{XZ+977>y!%GhA>4UKqZ(3VA*9u6WXZTEO4|H-U&s=( zJ2IdlT7encl}2i!m^>inNmZ!Gp6!U-knP{@eE)Q>9@uu!zR7PLBU_11GsDl&erJY0 z>TdqB->W^>{(WW0QYYo!IhQmL+#Vvr|iXW$q0=LPMCy za5grEHm+U?_%ZE{-K<(wp2^ls+B|0r= zgUJ||Ndnql5~5=6!$c$3IOTr!6!Ugx6LuYGvS@ZJ{d`f$mHTK=#^Edbq^BpB_-5kH z>|3t+eOwa`Xn8s^guu@9EG`|>uks-xT6^_decHOYL$xWA`zR)aHCSfEsY(1bQ9fA> zSJ>=vWN#ap$RUH>dfKU6-^R2=PytgyG2Gehm|=5&IAJ@B8YW99wA>LkxG{7Q)EGu7 z$yO?9$s-*4i=U$4Zc1ZlIg4N@bLZeZi$QSFb@hTb8AG}%{(?)UC%$w1|AeKj@ACLHT(k&e8cQ=MZKK|}} zkOeiBvtkCGWf6{hI#?)<#z(FG)fn}_0j_)(sJ+0)j$^@f=6w8lm)>H`6J@v}|JB86 z_NAsGhG`FziLMMgY3^_O`Vw=Dp&vHMG}QW7YnPU=*-AWwOcYbOLK3Hmp}yhmxqr-x z`lS&AO?l6-9U+=voeUpAKU4tyHz6d?_GcyW`r#Iq<|o07K;%#>Vg(Dd09z?aKTbUF zsbp(GcCSqZ8md5m9#T9y(BH|1Go_n1q4!+)CQMA~RcDFQSq0cifscrea6D^VS;jvj zk!M{t_N@2~HCpEb2>{|Q2qlh^u z6N2ts8&WfRr&>P3Q%FkS!CV_Qan~Z~QLS+#33#}z$ZEM$aw%KafuQF$ACK1zK-`Cc zau1)jq_yI9B~sO~QT9tpw-%S{K=;YbGh)sKx!Sqs?z5RpwttEA?~}OM#tBWiXHbu6 zZDmAG+!UUfZH-$Ny?K^q_0H=P9D^lKGW5AuxZ{=7J{Q1M6vOr>#;%3h16{Diwzs^n6d+ac0NjQEo{8ACy2)6S}q z;G~v-a9mO>GiU=|KIYCKA71rtyWPB=YQO~GJ@PU8kpVX1w#`(<0>dvl?{zfx1bka1k-n>sRy7AB$Tr68h7?O*JO zxi5}{2+xOOx+rKR=!!q58&A;yB{=V)9ev1gOP3)mgg|ef^s&pZdkjzdb#ogkl8z-) zJHzBE2`o4A4uwD6Bis+4O588&bH2LZwxZE0r+GGmM7kmS)!cd3L413zSoWA5rH`dJd zWUTdNc3YC=v!uoi87>#y}Z?a5-BTm^~{QowvD#*eOAwQEMXSbz1qOw5ZV*K9z|?B@D9eVv4pVG+8 zLHc&EmE2t1u{X0-EpNIZwZi|~cm9sICr;UtHL)pwSs?KSLk*9*bxn$@T&pXemI z!O$&VO?i!i6kqi&q87DnLeoi0Up+_avx@s>CCf*}d&z^C=!j3ZrK#lx_O}U-1m2#7 zqKksBewj>-sVLBbmI|#}iCF0DhHI#*H*gM*wCMUaYK^efDBrJH;~=xf9i0H3TT)%K z_?_bH!Pq#KG=VECYBoC)hsrjg(!?(F7|F>t_2i#Gs$lxoEaiJi+v!3}5lhKZEPAM>_m3y(;MWpzyZE%d~+d@wD2NZ{_+I~s&zAu2r_Ja&lI+s5}el;Fj6DkMO8 zHYwbpKg$1jZ?=JFEwJ8*Gg~bW7Rn$dz&D>D?q!WfYpDU!n#&vVuwuT5ivH6fhWyDE z%v76?#?J&xfDQg*UG)Z5x6cL@t0IX`5cWOw!XLo;x9Z2=`O@o7t6Q8&yUC9vfGFq> znXV8H8f^ne36l$j!wXQD_6#DvWHz+7Pg^W4RGIR*ih58UI{lmE=4HrM>&xioud(}TG6AWpq5&()kY|Za5d!D+iDKn0r&!zib3VXebe3F ziGdS@IZ+m$qe@?SADl#`{|gMt8z@DLeyF^34jw>IRAS4MgNPjJDkI^_RGz!fUf z(8?Bm=tBa<7$j`K<1?onPgSR_ZNLxg+yduO%VZd9Yk=w<58vv)BM0$w!y4c*Bpb#K zXgM|dWA1dOH4)cCI^d^Sc%7*|Hh zNW!qn*fVi8)CLrCU4-97)Ajg7;A+%os*+f>g-v-H*Q-cjhmfzd#;~Zv#rBnF**o zvN0CSP>0||$`U$NK6$p+_~EhNkG~HK(8>Rb0Ey-b3_fAP6t zSWwI?HFKQlT2o9r(LHlmeASnNg+CqlNJC)7Ok1rM(XkPWTF2or#wR$tEr*8@jD-jB z_Pft-(u3M^rpqu;iRqORtKJ8m(6(|WxPmT{%mZj$;;P`S<&rQB0vg+P<(Fhn!}VC? zOqjJnB?i*+dM;clU~6q9+Sgz;CcGNJK&>H#Wp-sSM^^b(^2(|B!~j~B#J}V9A0>*~ zRH>3ejyVw8(F(Qc`}m9@ygN4fPo!>6fAPvErOFOtexqN$Ma~DxE7=HV)1_)4o-vs#*NaiIGa9L zk5E^i(v~<44CfavLIl<;l_n}N%c;Rl>@3}oE;Z}eQVp(6_K3aWRGHl&Yd)H~hMg`2KG__J@@@9cV{j@TWziG+Ezok*YoK z*T$=5LwnH4b%R#`l`bh{h0BKGx<#cI%{PsgO-$B3#peYF`?1v)v=W)szZR9qE5byV z6{v<*6H45vi_!|t9A9-Xuz|B+r3#ZIw3F{q4AY)_h)t~BLdX9qfsFZ!DC@&ZO`n$|@%lFa NETtq_D{d0`yPYIzKiT3*|YC4wyc?veP6Sa>|4%^ZHS^oB|>(xOtu)zAX||=`w}K( zPgxSa=X3r3`FF(O`+6r^3_?GK^6Os%yCX+mV9C~TYtFZ}{bEjGrz??~#jyW-H^v(> zvb2QIfsu8Ch2>p>`Qi*mylZZkvCkUe+4ot^TE3X(jNVTw9^L1^XxS>CSN(H?L2K&ECyJIkFrCntx)bPdhCXlwDW z!WseLj^O~0+gTrj+BGs_34!-}(dsZAmra*R_=Vb0`jhYOQWUpzT@r@-^0~RaG@dWi zJa_rDWG#L*S2dgt4TprNv^$d2K3LYkX=L5icnMLWLP3X0MBV}QhW>eI|5PM4OIeGgRn@YVtr zPZE9nR8xqVWSYEyR;!T9UXqQUk(OxyX=xYViNdzKF%0NTCpvg(bFN9N<|HQ-s)a@O z_3{DCDJTaVs!4%@i2dayr=Rp;&O#;yvVV5&EX98M)Is{0zMyaGq>rv|6>lK}IRQqX zab}d`V1{s0B~m)pDpuv;C+S6XI$@lHQf`c?&SS3%;_1wIaF%%9>yM#+3IspcRW?mG z84?w4DzmWv5UdiDqv$ZCc;3L4tMD=afgbunSf}pVO9xT4IbK)dGO<)WL6c8GOE=7x z>y#<}#wDK!z#$Aju!p3965=Rzd2$5|sgo21AQ%UM)JowTZkXkosXy`S)GZnvnV(NP zct{zx7v}bGlw2q?5lOKh0S&|n1S;he+#9H$HR!z&xEI#lxB*QafNH@B05kj(w`OJ$ z?38Jd%mBc&1r@sLf#(3959 zwPPhHQgxx~_$y2)f>jIXQPP4z7AQUG{%kwAC}!g`tOYj)+!UjhA%iT57&K(t@j(bR z%;lLrVQ(P7YT(5h6OiFc=8UzTt}mlrT~({IjxVozqr=D7^{>sz&nxCT*igX$mJJwlVd6>Kl317l5#0>y1>agIzIIR8B$ZCq$Mot+@5o;RMEO z#zY2g@NpjC$O@6kY);!rQ_&2CNQxMBPJe&ef>EzPmAq@rK)*X~mksw&%A@Z`{b-#r zjtz(Vew$q^edvyzb^y+>?0qn5Ekr#(e;W9`!HC*`TEvLGbSN=vVq6|6)D~;~@nZJB za|8o#OT1U}ec{iIDo6X0!Whn%WnR-f(=RSifiSdx`*r#+E#w`nhL(w>&aIDb@axx= zuX(EE!IBIB#r|ipT6l%IhlA^rs$f#m^-lMvg_WWdnD{uyVZFO|uh4PZYSD5jrAz-{ zkF(H3(ox0S=H-^>R{D^zKsY^ge)^G&vGd&`10EghowlnXt)Zsgv} z$v-8oK6iGa{^Sm6dY|^AM~}Wn`=Yw)ivWSy%MXW`cYvtfTSk z1RRF?6q??*dY`+-Dt;kgIMVmN6g#|3Z<3Iw8jk)#6kspjKf&^9eTSy?f<=CY^&T&! z!AS#A#i>?NZq8d?U5JI^k{N_BHZKFjB46+X^V6m{0%@6pDz zZTY1z7>Nsys_HxNo1DB91xj~q! z1VJsVS&*r2At2#HIr?2G*tN>GeVpA^ndL`34ttyUeyrb6ijYd@n0{3Zn{5O3XWJ-d z<1z+~Ml$`iNU=i?zB3%uk zrV7V-g-&u9Eb}c2_yplseQb7{C7s2x5h2It@Pi4Il8AYDu+sBKc9CRbd)wa3)4Aok z06_&q_J8~4szP0TeLdG7VGg!ij^g30-{joMtk>PsAZuwhPCy2ubDlQTInPW%V%f%3 zqB4REimr?DYHx3U0p}C;E)>e7bc#K_K?_-oSf#B*(z^yMwq09_J@fz8c%hYTmi+fU zD?7+)yXF81??U|f(Of2#6#K^3mRRyqZO30xPsi(DY$Q*A)?1cO<4}u>jz7EUHN=z0 zB9FFha+QNi0fw4yT&$cBFoaO1_t2@Wuel$DA^VEW6=BA?CjYbLjnN{{NHxcAF_{Ai zyuiPMPZJa7P9j^n&;lJ}W8>enw6xrNyStWFR#s(e3muO*@fUxqN+>fPMjM0_^A$ppFa$*0kW1{N;_L~41VSW>>wnT#94H?_7TgN71x`gQjzj*)_YhIq(1BJ zI6?!Ecu^&7xoo!}%B}$htlkie!Bj!CJqEWE>oN zA?gvPEblF=e$?VGX5YjZW6#-AtL>UAqoaVRsQl<%%UuWf8<>b*SBF}1Uc-uav* zmSgl%GD{F*M1K3CI~f#j?2Wyf>z>j1#6H%^0dkg3VAR{s&zw3@E4jzDp`ihQ3$wU_ z*dx~S!Y6Jb-nLnqnH4#X4ah~73_wj8W`XB4-0BpZD!j|#h zr6Oc%jMty|(Oyyl)2$482mthNko;i`EvG^;nU=3_m91!2WuvXXP5y?BL>e(aPyF{_%ks;RBZ`jQge(dp@A z3A-k^+PI08* z(`>#XJ8~QBn|glZSwyo8&wJRM?C0t|>B*oZ;#a9FtEwj7DEQ~71pgRZ^h2!ujp+bD z5(NH^dZg#z;1F$RXNS92VNBLldiTx9$Or@tM_D;NvXEd(aaMR^YGF~b`0?TD#CksP zc5=@){$T&Rb~W&Y=yNMUwsy+b7$MelN!&l0dvF}E)WHq*O;Q8gJ-v9i5n*Y{c((QTt>Wl7p+l{BZ=b=UhQSq06Jbu)2EZfnvaX zKQVlW0BXGhL|xdDMEa5n@*4P#l}SSc2U=KU0ie0A6nI84=n>4H*ZsW!bkQKC^ZEhb znJaKcI?UwN)EZ96uEUQ@m{P~meFHkA1rA7JULI4}88*(9*t}5UPpdked zn;|Q+jlOOVI!-rAZt{jSIN@W@BmDiV`4{#; zk`+vC<@Y|ADQ8EYm%McRy9_i=IjVL%SW*x5_m@xzm{0!s(+70;6p32)?NO}3!ND0{ zi2D(0uX1w}?i4*78XWX;m85e!nbpZH!Qgajyr9~#FtK% zsXeY>wzb8tc7G3C{#I@GF?gM>x3BNuY!8pS%EtC2sHJUT{jkNu!y_#W=fF&dSuof& zS$|Mt%udsbmseE0#Mw(eI6ga<%p5Rhz?Z~nR+Wf+wBOA%vA$C#$onRjCxdK)rToS9 zT8azSuHb&gk5 z?u!Q>8SRigo%02=Kp>+1|a5(;*Fc`_J z5wLw}Qa0YYufzvx`$7x29jxnC>;3Q^4y8q8+|tNq8`VqOwCOqGEutSK z`sw;hD!1(dW3}MOBPE4qDX5AzNJtLrnxk7(W;dcU`TY1CalCuQw0S|&s!2N zz!O_)JB|4EQv?*R=iCURSbNp%d>Q3*qSLQ4`IqGrjelLwZoa3xBOwu54a6$vJrDA` z*DA<>j5nNwK3;Yrk?9j=r=fx?9ZiS5GYZN@8-*gbEuIuZgyR4$l9bq6d|#RagWmp^ z9~Ce^|Am4jZrDEhM&A5eR^BPWm%0x;Qm68X?n>@Z@My3U;bkzjCj$MgkdRnb@jq{~dJ0RjrDb@NE< zDUl82Nr~WF)o{s!i}T|pkmneaGHoNHFCQE&L|H+SFsskb&ffb6od20R*{&bXflIR9 zFU!TV=59&*XiPcUiP|HNOi3IuNpGMTXOwl1Ss{Hnv87hg-ZW4Txz2g1mtX3A>d=6 LYob%5cRZEv8-C5~6*{5g$R2UXI7Y{@NA{i(vLYi6`r@_s4B0E$vI$2BB}sP3I#xEB zkvPB8=l6WxznyeBRCMD zhz6!qc_uLROv!k!+}a(gIHkD}d&YLU*UTX8UfF6y-%zaR&ew~YD5&7_A|&?IT0x-Q z(pD&wRv)_69b+lGc)7ZW{|g>B=yd%4d)Q%Es_Adb1iX`OD z+Mk!kCosBo(#ZtBe?PpS0IFU(-VAtR7Dl)Jcx_L@b8@x`)UoJX4mw1Uf%T^zfL+!P z`Z0={b$s`a?-c|ok?^PNg*q&B7IcqN!uC9wdh+YWIU?ty&h%2UVPBtfRox9PhPGix zGB%nDVVh4tVRF9O#NL-||A$K$Kic4Kb}CX%q{D`NZgzI)!n2W?>aw!3dcOmRgBX2? zHShz*_~pa8HwVKQES2g>bAC=v@64iTjKkgCUg73q>Z6J~+RA-;G?@4H_Fzh^a!;)_ z%91tW$T>iqg-a>>Ul`y#5DAAQSPj(Xcp~yd7wj5}TBf3HQwVKIYzga$SrW-ZXd-*b zk_XbpzD;ivF}<;kWa7!HkKl&8XpJgFi$+^lk3_>%2uuWR#RwigEE3HI@@XPPo2;d8 zdK?-kKZx!N9l3$Xk1qlz%0D#h`I!Zvl^dh&ySbGXff3Rx|fnhL_t za@d0Ktyg(EaC0GIg0`#Rw%*4xxj98IdFL`@FEDeKB-+~AkUI~6wAkJfwcr`If=%X- zSs{YLC8Aj6mt*@qn*@416xV9O{%%nGN9;zR{*~cmt)BIPC%_Ze%h}B?natZrLI{7z zh5hZ&D(DpF4U&JBB&;_R+MS({yx|;zKG+Yz^Xoj_Qcl_F z1tm2P&#K9d_$(6Utq^O!V!!$M@w@VB%2he2S$KFwZeD~9S8tdB`C)_o%tGoj(|yKu zhLqSD!!SL*{)ZyIeXG(jws10JVPb15>8P_ff-R{TWc{p++0X3og1Zj8Kg&>l!7ubMFtz)w4H_7p2coA?g%w_3Lwrswu( z=9mR6^3BQt`b5(=s9;CQLk?mQeaoHO0BX%*XybTdJeH*m8FQm2>5eR1N-7%Tckpw# z9Yn!;s_VKaN)58T;v~wxQB&pJNRy7LsseV=6fYjIOGw;7_&DE|@Wje}%CaXjB0ar5}Pz(-8Ab+LVk>!-(fa# z;0%BD_{%}JcXpbPmY9WSR8%J=UBM7g!1zJG9l4|9*LsUP^=5Znv2z|y`b0PWh+4@f zyfA*iWk>$?z9XWB#;R3$sz(S-bahq14vnhng4)Fr-*>!ULvuq&U*gvug(1;xU}gFN zG&$3&?GdG9?!BFosmV#k&660Gw&xqdp6!9egp37phYEaF5g*{hm>_vc_aEtwppl4MRY2{;rED0s&B5mQ;)Qqt?uuS}sc|640VX#z={{k(%Qtv^x z(|s)>jmsI|`;z~%Iy5m+cM4TKb#sBx%q#_q{lMmGYahnq44(GbpTcaZQH?MKT^h_M zVu{i1L*-T!K*>N(W75cC=4Q8T<>Yj$_R;$C;(GbuO{4Qt(fg8)`2L*gj`Xe!ro%I1pzr+$1v6gW4@|KzLxHj9yO1+FiF$vo zs^`|$3kXkG6}a6n>-@R+8+T&~+)iY6T*P z2GxSTQzqELW8PZ6V{RE;3clQPA%RexoSv?KJealt^Cd(I*K5+PPR&Kq_q1(2JVZ{% z)Y#Wmw&eah6Z)1XoknZAlhjBZg4cV=SlfQ!Td6OS0GVKk!&5@RMEAMYApeuiu_iev zC}Q6==G?CqN$yj1k zYJ1?t(PC;UJ&?M%w6x?gy5++QY8tb9)9Mkbs;S8@bOt=Hn{xg5_wQfat43iiK(l9a zbJHb5(>Ku7l|r@T(1(9Vk+4X4zBAxhd0V6@J*<%$u!k<4rRv&<)|gcD)X|t~%#xyz z#%&|WOCg)u?{~OqL+)9&Vh7m4ukm$OjcDYMIseC3v!+UeM6g!jBC9W8z#{AzVA2^> z3vn_}O>cV{lfn+ca}ypO{_&pp^7J6SvBG6#FTbLR@dU!?$Rehc3>A7nV0)*| zBaOQHjCjaD>$#DXU6mlOD(T?wFijUH+yH3JT)Y;z=t@dGd;ZGCtL@g{V@V=_y z$q;krS%OBr-1Hy1Mb^ysYS^4U99N=nLZ;Jn++g5WPs z3fMTp{b*YCk!fM0+3NoHFvv(Y)GlHhIo#knil&qjf=V4Sw zX=x-yq+(8Mt7Oac&c{SnDe-^Wh>eVl6ffM#KG*$JU*mxTsQU^Tzc*_MjeLq1h8S0X+I}G_HsVX(w+wpv5S-WRktkmY0&6?v z2r9t`^;K1x#YO^C%bpOPH2#8b%bt4H)`@uK>NtQkyF^7~k&3QOv%6xs!_%b(TS;eU zXMG3ne?tMTSTi?CRIjL`|<-HdNHexwHx#RZDFy1FvrDci=UdtURX zF8ZULLQoJGBqz^E@i;gbDx5h)j)jNdzN~x+afSiTeh9WU^xlsdOON+cvQko+KaUSr z2Rvo+hc2v4`%jGTjkE5zIoYmA_ur#v zyzu@U23?+2K7IPM!E063$kepYO;U-Eabb9Ib1)tH@b6*H%2-oW9K!g=jb#9-qlUX$>kF?HVAoP`RE35aW0FYgtK4 zM@O-GN`{w*M;w~$j6LJp_GwyCt=S^0Tv}t)>cP)euj_ z1+mjsW&3y&sY2*qaOB&!GklLY-lY`j1ma%XHq91Ix#r8{>+E>9*YcXl(r;BpZFUh3 z9y8n$oBU&rKcbP>A5f4YMgDu4Gj!yaE&-KW*@Q(Q*CLNP&kIbducA>fJp>z#nb0fB z;BJs-nU3f#bws+jQdCZDq~f^{g+^uwqMe0LLSAW=`;G;O!UcEZY|_%w*c_l?E&e)D z%Lct>f1YUUylS6ovhG`5`;z=K^7OHit4Z+{=Xjrd{{&3^&JnqE5r_8*@@t7M@5^!p zrq6ZEDSLkeVxL9HWf;=;cR6Nk>7ZMj6vn7_001tSG_?C6v1CX)V}BuX*eNW zobX(dl*TJ)n-!4?t}2xdAo->HnKSi(#NnJ-=X*g8|GiR$oBYjS?+;tOn6Fb#d7cmV z{++bALGjhi@1&emu=I{+^4A;z&N{=E#f*A-I546m)rUMLwK~+`I5U;-|5=9}iw*!)a0F6U7r- zqvPX^ue${@C{|Zjz1ZE|-8HVeFMhHHUSDiz!!qMu8h-I3akA9W=DS-;6*BW%e}jzs z&7=qA$aD$E{VfPZAC3q|YExZvKCc1bhlYxda;>6m*#7`* CVQ9+$ diff --git a/marklin.res b/marklin.res index f2f69f3..bea052d 100644 --- a/marklin.res +++ b/marklin.res @@ -126,6 +126,13 @@ graphic "digidisplay" border { top 5; right 5; bottom 5; left 5; }; }; +graphic "tooltip" +{ + texture "gui.png"; + slice 72 90 20 16; + border { top 2; right 2; bottom 2; left 2; }; +}; + graphic "hsliderslot" { texture "gui.png"; @@ -143,14 +150,14 @@ graphic "hsliderknob" graphic "switchdown" { texture "gui.png"; - slice 46 43 20 21; + slice 47 43 20 21; shadow { top 0; right 2; bottom 3; left 0; }; }; graphic "switchup" { texture "gui.png"; - slice 67 43 20 21; + slice 69 43 20 21; shadow { top 0; right 2; bottom 3; left 0; }; }; @@ -295,6 +302,23 @@ style "label-digital" }; }; +style "label-tooltip" +{ + font_color 0.0 0.0 0.0; + + part + { + graphic NORMAL "tooltip"; + }; + + special "text" + { + align 0.0 0.5; + fill 0.0 0.0; + margin { top 2; right 2; bottom 2; left 2; }; + }; +}; + style "hslider" { part diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index 71391ff..ba804f2 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -9,10 +9,15 @@ Distributed under the GPL #include #include #include +#include +#include +#include #include #include +#include #include #include +#include #include #include #include @@ -25,6 +30,7 @@ Distributed under the GPL #include "manipulator.h" #include "measure.h" #include "selection.h" +#include "toolbar.h" using namespace std; using namespace Marklin; @@ -36,6 +42,7 @@ Designer::Designer(int argc, char **argv): screen_w(1280), screen_h(960), base_mesh(0), + cur_route(0), mode(SELECT), input(0), cam_yaw(M_PI/2), @@ -72,17 +79,11 @@ Designer::Designer(int argc, char **argv): if(argc>1) { + filename = argv[1]; DataFile::load(*layout, argv[1]); const list <racks = layout_3d->get_tracks(); for(list::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) - { - if((*i)->get_track().get_sensor_id()) - (*i)->set_color(GL::Color(1, 1, 0.5)); - else if((*i)->get_track().get_turnout_id()) - (*i)->set_color(GL::Color(0.5, 1, 1)); - else if((*i)->get_track().get_flex()) - (*i)->set_color(GL::Color(1, 0.5, 1)); - } + update_track_color(**i); if(!layout->get_base().empty()) { @@ -115,13 +116,9 @@ int Designer::main() dpy = new Graphics::Display; wnd = new Graphics::Window(*dpy, screen_w, screen_h); glc = new Graphics::GLContext(*wnd); + wnd->set_title("Railway Designer"); wnd->signal_close.connect(sigc::bind(sigc::mem_fun(this, &Designer::exit), 0)); - wnd->signal_key_press.connect(sigc::mem_fun(this, &Designer::key_press)); - wnd->signal_key_release.connect(sigc::mem_fun(this, &Designer::key_release)); - wnd->signal_button_press.connect(sigc::mem_fun(this, &Designer::button_press)); - wnd->signal_pointer_motion.connect(sigc::mem_fun(this, &Designer::pointer_motion)); - wnd->show(); glEnableClientState(GL_VERTEX_ARRAY); @@ -130,20 +127,30 @@ int Designer::main() glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_CULL_FACE); - GL::Texture2D *font_tex = new GL::Texture2D; - font_tex->set_min_filter(GL::LINEAR); - font_tex->load_image("dejavu-20.png"); - font = new GL::Font(); - font->set_texture(*font_tex); - DataFile::load(*font, "dejavu-20.font"); + DataFile::load(ui_res, "marklin.res"); + root = new GLtk::Root(ui_res, *wnd); + + lbl_tooltip = new GLtk::Label(ui_res); + lbl_tooltip->set_style("tooltip"); + root->add(*lbl_tooltip); + lbl_tooltip->set_visible(false); + + toolbar = new Toolbar(*this); + root->add(*toolbar); + toolbar->set_position(0, screen_h-toolbar->get_geometry().h); + toolbar->set_visible(true); + + + wnd->signal_key_press.connect(sigc::mem_fun(this, &Designer::key_press)); + wnd->signal_key_release.connect(sigc::mem_fun(this, &Designer::key_release)); + wnd->signal_button_press.connect(sigc::mem_fun(this, &Designer::button_press)); + wnd->signal_pointer_motion.connect(sigc::mem_fun(this, &Designer::pointer_motion)); mode = SELECT; Application::main(); - delete font; - delete font_tex; - delete input; + delete root; delete glc; delete wnd; @@ -152,6 +159,41 @@ int Designer::main() return exit_code; } +void Designer::save() +{ + input = new ::Input(*this, "Save layout", 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; +} + +void Designer::quit() +{ + exit(0); +} + +void Designer::edit_route(Route &r) +{ + cur_route = &r; +} + +void Designer::add_selection_to_route() +{ + if(!cur_route) + return; + + try + { + const set &stracks = selection->get_tracks(); + set tracks(stracks.begin(), stracks.end()); + cur_route->add_tracks(tracks); + } + catch(const Exception &e) + { + IO::print("%s\n", e.what()); + } +} + void Designer::map_pointer_coords(int x, int y, float &gx, float &gy) { float cos_pitch = cos(cam_pitch); @@ -251,12 +293,11 @@ void Designer::tick() ss<<" (turnout "<swap_buffers(); } -/*** private ***/ - -void Designer::key_press(unsigned code, unsigned mod, wchar_t ch) +void Designer::key_press(unsigned code, unsigned mod, wchar_t) { unsigned key = Msp::Input::key_from_sys(code); if(mode==INPUT) - { - input->key_press(key, mod, ch); return; - } if(key==Msp::Input::KEY_SHIFT_L || key==Msp::Input::KEY_SHIFT_R) shift = true; @@ -300,12 +336,7 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t ch) mode = MANIPULATE; } else if(key==Msp::Input::KEY_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; - } + save(); else if(key==Msp::Input::KEY_PLUS) selection->select_more(); else if(key==Msp::Input::KEY_L && (mod&1)) @@ -359,11 +390,7 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t ch) if(*j!=*i) (*i)->snap_to(**j, true); - Track3D &t3d = layout_3d->get_track(**i); - if((*i)->get_flex()) - t3d.set_color(GL::Color(1, 0.5, 1)); - else - t3d.set_color(GL::Color(1, 1, 1)); + update_track_color(layout_3d->get_track(**i)); } } else if(key==Msp::Input::KEY_F) @@ -413,6 +440,8 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t ch) mode = INPUT; } } + else if(key==Msp::Input::KEY_A) + add_selection_to_route(); else if(key==Msp::Input::KEY_RIGHT) rotate = -1; else if(key==Msp::Input::KEY_LEFT) @@ -506,24 +535,21 @@ void Designer::pointer_motion(int x, int y) { y = screen_h-y-1; - float gx, gy; - map_pointer_coords(x, y, gx, gy); + pointer_x = x; + pointer_y = y; if(mode==SELECT || mode==CATALOGUE) - { - pointer_x = x; - pointer_y = y; tooltip_timeout = Msp::Time::now()+100*Msp::Time::msec; - } + + clear_tooltip(); if(mode!=INPUT) { + float gx, gy; + map_pointer_coords(x, y, gx, gy); 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() @@ -550,7 +576,7 @@ void Designer::apply_camera() void Designer::render() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); + GL::enable(GL::DEPTH_TEST); project_3d(); apply_camera(); @@ -564,37 +590,37 @@ void Designer::render() base_mesh->draw(); } layout_3d->render(true); + if(cur_route) + { + glColor4f(0.5, 0.8, 1.0, 1.0); + const set &rtracks = cur_route->get_tracks(); + const map &turnouts = cur_route->get_turnouts(); + for(set::const_iterator i=rtracks.begin(); i!=rtracks.end(); ++i) + { + unsigned route = 0; + if(unsigned tid=(*i)->get_turnout_id()) + { + map::const_iterator j = turnouts.find(tid); + if(j!=turnouts.end()) + route = j->second; + } + layout_3d->get_track(**i).render_route(route); + } + } manipulator->render(); if(mode==MEASURE) measure->render(); } - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, screen_w, 0, screen_h, 0, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + GL::matrix_mode(GL::PROJECTION); + GL::load_identity(); + GL::ortho_bottomleft(screen_w, screen_h); + GL::matrix_mode(GL::MODELVIEW); + GL::load_identity(); - glDisable(GL_DEPTH_TEST); + GL::disable(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(); + root->render(); } Track3D *Designer::pick_track(int x, int y) @@ -613,9 +639,26 @@ Track3D *Designer::pick_track(int x, int y) return l->pick_track(xx, yy, size); } +void Designer::update_track_color(Track3D &track) +{ + if(track.get_track().get_sensor_id()) + { + if(track.get_track().get_flex()) + track.set_color(GL::Color(1, 0.6, 1)); + else + track.set_color(GL::Color(0.7, 0.7, 1)); + } + else if(track.get_track().get_turnout_id()) + track.set_color(GL::Color(0.8, 1, 0.8)); + else if(track.get_track().get_flex()) + track.set_color(GL::Color(1, 0.8, 0.8)); + else + track.set_color(GL::Color(1, 1, 1)); +} + void Designer::manipulation_status(const string &status) { - tooltip = status; + set_tooltip(pointer_x, pointer_y, status); } void Designer::manipulation_done(bool) @@ -632,7 +675,7 @@ void Designer::measure_changed() ostringstream ss; ss.precision(3); ss<<"Par "<(ui_res.get_default_font().get_string_width(text)*fontsize)+6; + x = max(min(static_cast(screen_w)-w, x), 0); + y = max(min(static_cast(screen_h)-h, y), 0); + lbl_tooltip->set_text(text); + lbl_tooltip->set_geometry(GLtk::Geometry(x, y, w, h)); + lbl_tooltip->set_visible(true); +} + +void Designer::clear_tooltip() { - int w = static_cast(font->get_string_width(tooltip)*20); - tooltip_x = max(min(static_cast(screen_w)-w, x), 0); - tooltip_y = max(min(static_cast(screen_h)-20, y), 0); + lbl_tooltip->set_visible(false); } void Designer::save_accept() @@ -660,11 +713,7 @@ void Designer::turnout_id_accept() unsigned id = lexical_cast(input->get_text()); track->set_turnout_id(id); - Track3D &t3d = layout_3d->get_track(*track); - if(id) - t3d.set_color(GL::Color(0.5, 1, 1)); - else - t3d.set_color(GL::Color(1, 1, 1)); + update_track_color(layout_3d->get_track(*track)); input_dismiss(); } @@ -677,11 +726,7 @@ void Designer::sensor_id_accept() { (*i)->set_sensor_id(id); - Track3D &t3d = layout_3d->get_track(**i); - if(id) - t3d.set_color(GL::Color(1, 1, 0.5)); - else - t3d.set_color(GL::Color(1, 1, 1)); + update_track_color(layout_3d->get_track(**i)); } input_dismiss(); diff --git a/source/designer/designer.h b/source/designer/designer.h index 8dbc9d4..e103a74 100644 --- a/source/designer/designer.h +++ b/source/designer/designer.h @@ -15,6 +15,9 @@ Distributed under the GPL #include #include #include +#include +#include +#include #include #include "libmarklin/catalogue.h" #include "libmarklin/layout.h" @@ -25,6 +28,7 @@ class Input; class Manipulator; class Measure; class Selection; +class Toolbar; class Designer: public Msp::Application { @@ -43,14 +47,21 @@ private: Msp::Graphics::GLContext *glc; unsigned screen_w; unsigned screen_h; - Msp::GL::Font *font; + Msp::GLtk::Resources ui_res; + Msp::GLtk::Root *root; + + Toolbar *toolbar; + Msp::GLtk::Label *lbl_tooltip; + Msp::Time::TimeStamp tooltip_timeout; Marklin::Catalogue catalogue; - Marklin::Layout *layout; - Marklin::Layout3D *layout_3d; Marklin::Layout *cat_layout; Marklin::Layout3D *cat_layout_3d; + std::string filename; + Marklin::Layout *layout; + Marklin::Layout3D *layout_3d; Msp::GL::Mesh *base_mesh; + Marklin::Route *cur_route; Mode mode; Selection *selection; @@ -71,11 +82,6 @@ private: int pointer_x; int pointer_y; - int tooltip_x; - int tooltip_y; - std::string tooltip; - Msp::Time::TimeStamp tooltip_timeout; - Msp::Time::TimeStamp last_tick; static Msp::Application::RegApp reg; @@ -84,10 +90,18 @@ public: Designer(int, char **); ~Designer(); + int main(); + void save(); + void quit(); + Marklin::Layout *get_layout() { return layout; } Marklin::Layout3D *get_layout_3d() { return layout_3d; } - Msp::GL::Font &get_font() { return *font; } - int main(); + const Msp::GLtk::Resources &get_ui_resources() const { return ui_res; } + Msp::GLtk::Root &get_root() const { return *root; } + void edit_route(Marklin::Route &); + Marklin::Route *get_current_route() const { return cur_route; } + void add_selection_to_route(); + void map_pointer_coords(int, int, float &, float &); private: void tick(); @@ -99,11 +113,13 @@ private: void apply_camera(); void render(); Marklin::Track3D *pick_track(int, int); + void update_track_color(Marklin::Track3D &); void manipulation_status(const std::string &); void manipulation_done(bool); void measure_changed(); void measure_done(); - void move_tooltip(int, int); + void set_tooltip(int, int, const std::string &); + void clear_tooltip(); void save_accept(); void turnout_id_accept(); void sensor_id_accept(); diff --git a/source/designer/input.cpp b/source/designer/input.cpp index d56cc1b..42cc078 100644 --- a/source/designer/input.cpp +++ b/source/designer/input.cpp @@ -7,6 +7,7 @@ Distributed under the GPL #include #include +#include #include #include "designer.h" #include "input.h" @@ -14,81 +15,48 @@ Distributed under the GPL 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) +::Input::Input(Designer &d, const string &title, const string &text): + Panel(d.get_ui_resources()), + designer(d) { - if(key==Msp::Input::KEY_ENTER) - signal_accept.emit(); - else if(key==Msp::Input::KEY_ESC) - signal_cancel.emit(); - else if(key==Msp::Input::KEY_BACKSPACE) - { - if(pos>0) - { - text.erase(pos-1, 1); - --pos; - } - } - else if(key==Msp::Input::KEY_DELETE) - { - if(pos0) - --pos; - } - else if(key==Msp::Input::KEY_RIGHT) - { - if(pos=0x20) - { - text.insert(pos, 1, ch); - ++pos; - } -} + set_size(300, 100); -void ::Input::render() -{ - glLoadIdentity(); - glTranslatef(300, 450, 0); + GLtk::Label *lbl; + add(*(lbl=new GLtk::Label(res, title))); + lbl->set_geometry(GLtk::Geometry(10, geom.h-30, geom.w-20, 20)); - 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(); + add(*(entry=new GLtk::Entry(res, text))); + entry->set_geometry(GLtk::Geometry(10, geom.h-60, geom.w-20, 20)); - glColor4f(0, 0, 0, 1); - glTranslatef(5, 35, 0); + GLtk::Button *btn; - glPushMatrix(); - glScalef(20, 20, 20); - designer.get_font().draw_string(title); - glPopMatrix(); + add(*(btn=new GLtk::Button(res, "Cncl"))); + btn->set_geometry(GLtk::Geometry(geom.w-90, 10, 40, 24)); + btn->set_style("red"); + btn->signal_clicked.connect(signal_cancel); - glTranslatef(0, -30, 0); - glPushMatrix(); - glScalef(20, 20, 20); - designer.get_font().draw_string(text); + add(*(btn=new GLtk::Button(res, "OK"))); + btn->set_geometry(GLtk::Geometry(geom.w-50, 10, 40, 24)); + btn->set_style("green"); + btn->signal_clicked.connect(signal_accept); + + designer.get_root().add(*this); + const GLtk::Geometry &rgeom=designer.get_root().get_geometry(); + set_position((rgeom.w-geom.w)/2, (rgeom.h-geom.h)/2); + entry->set_focus(); +} - 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(); +const string &::Input::get_text() const +{ + return entry->get_text(); +} + +void ::Input::key_press(unsigned key, unsigned mod, wchar_t ch) +{ + if(key==Msp::Input::KEY_ENTER) + signal_accept.emit(); + else if(key==Msp::Input::KEY_ESC) + signal_cancel.emit(); + else + Panel::key_press(key, mod, ch); } diff --git a/source/designer/input.h b/source/designer/input.h index 9a4dbcc..2bcd16c 100644 --- a/source/designer/input.h +++ b/source/designer/input.h @@ -10,10 +10,11 @@ Distributed under the GPL #include #include +#include class Designer; -class Input +class Input: public Msp::GLtk::Panel { public: sigc::signal signal_accept; @@ -21,15 +22,13 @@ public: private: Designer &designer; - std::string title; - std::string text; - unsigned pos; + Msp::GLtk::Entry *entry; public: Input(Designer &, const std::string &, const std::string & =std::string()); - const std::string &get_text() { return text; } - void key_press(unsigned, unsigned, wchar_t); - void render(); + const std::string &get_text() const; +private: + virtual void key_press(unsigned, unsigned, wchar_t); }; #endif diff --git a/source/designer/toolbar.cpp b/source/designer/toolbar.cpp new file mode 100644 index 0000000..46994a0 --- /dev/null +++ b/source/designer/toolbar.cpp @@ -0,0 +1,100 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2009 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#include +#include +#include "designer.h" +#include "toolbar.h" + +using namespace std; +using namespace Msp; +using namespace Marklin; + +Toolbar::Toolbar(Designer &d): + GLtk::Panel(d.get_ui_resources()), + designer(d) +{ + set_size(370, 40); + + GLtk::Button *btn; + GLtk::Label *lbl; + + add(*(btn=new GLtk::Button(res, "Load"))); + btn->set_geometry(GLtk::Geometry(5, 10, 40, 24)); + + add(*(btn=new GLtk::Button(res, "Save"))); + btn->set_geometry(GLtk::Geometry(45, 10, 40, 24)); + btn->signal_clicked.connect(sigc::mem_fun(&designer, &Designer::save)); + + add(*(btn=new GLtk::Button(res, "Quit"))); + btn->set_geometry(GLtk::Geometry(85, 10, 40, 24)); + btn->set_style("red"); + btn->signal_clicked.connect(sigc::mem_fun(&designer, &Designer::quit)); + + add(*(btn=new GLtk::Button(res, "Trnt"))); + btn->set_geometry(GLtk::Geometry(135, 10, 40, 24)); + + add(*(btn=new GLtk::Button(res, "Sens"))); + btn->set_geometry(GLtk::Geometry(175, 10, 40, 24)); + + add(*(lbl=new GLtk::Label(res, "Routes:"))); + lbl->set_geometry(GLtk::Geometry(225, 22, 40, 13)); + + add(*(drp_routes=new GLtk::Dropdown(res))); + drp_routes->set_geometry(GLtk::Geometry(225, 5, 100, 17)); + drp_routes->append("(new route)"); + drp_routes->signal_item_selected.connect(sigc::mem_fun(this, &Toolbar::route_selected)); + + add(*(btn=new GLtk::Button(res, "AddT"))); + btn->set_geometry(GLtk::Geometry(325, 10, 40, 24)); + btn->signal_clicked.connect(sigc::mem_fun(&designer, &Designer::add_selection_to_route)); + + designer.get_layout()->signal_route_added.connect(sigc::hide(sigc::mem_fun(this, &Toolbar::update_routes))); + designer.get_layout()->signal_route_removed.connect(sigc::hide(sigc::mem_fun(this, &Toolbar::update_routes))); + update_routes(); +} + +void Toolbar::route_selected(unsigned index, const string &) +{ + if(index==drp_routes->get_n_items()-1) + { + Route *route = new Route(format("Route %d", designer.get_layout()->get_routes().size()+1)); + designer.get_layout()->add_route(*route); + designer.edit_route(*route); + + const set &routes = designer.get_layout()->get_routes(); + int selected = -1; + unsigned n = 0; + for(set::const_iterator i=routes.begin(); (selected<0 && i!=routes.end()); ++i, ++n) + if(*i==route) + selected = n; + drp_routes->set_selected_index(selected); + } + else + { + const set &routes = designer.get_layout()->get_routes(); + set::const_iterator i = routes.begin(); + advance(i, index); + designer.edit_route(**i); + } +} + +void Toolbar::update_routes() +{ + drp_routes->clear(); + const set &routes = designer.get_layout()->get_routes(); + int selected = -1; + unsigned n = 0; + for(set::const_iterator i=routes.begin(); i!=routes.end(); ++i, ++n) + { + drp_routes->append((*i)->get_name()); + if(*i==designer.get_current_route()) + selected = n; + } + drp_routes->append("(new route)"); + drp_routes->set_selected_index(selected); +} diff --git a/source/designer/toolbar.h b/source/designer/toolbar.h new file mode 100644 index 0000000..fe2357a --- /dev/null +++ b/source/designer/toolbar.h @@ -0,0 +1,29 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2009 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#ifndef TOOLBAR_H_ +#define TOOLBAR_H_ + +#include +#include + +class Designer; + +class Toolbar: public Msp::GLtk::Panel +{ +private: + Designer &designer; + Msp::GLtk::Dropdown *drp_routes; + +public: + Toolbar(Designer &); +private: + void route_selected(unsigned, const std::string &); + void update_routes(); +}; + +#endif diff --git a/source/libmarklin/layout.cpp b/source/libmarklin/layout.cpp index bd9ee71..234b923 100644 --- a/source/libmarklin/layout.cpp +++ b/source/libmarklin/layout.cpp @@ -35,10 +35,44 @@ void Layout::add_track(Track &t) void Layout::remove_track(Track &t) { - if(tracks.count(&t)) - { - tracks.erase(&t); + if(tracks.erase(&t)) signal_track_removed.emit(t); +} + +void Layout::add_route(Route &r) +{ + if(routes.insert(&r).second) + signal_route_added.emit(r); +} + +void Layout::remove_route(Route &r) +{ + if(routes.erase(&r)) + signal_route_removed.emit(r); +} + +void Layout::save(const string &fn) +{ + IO::BufferedFile out(fn, IO::M_WRITE); + DataFile::Writer writer(out); + + if(!base.empty()) + writer.write((DataFile::Statement("base"), base)); + + for(set::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + DataFile::Statement st("track"); + st.append((*i)->get_type().get_article_number()); + (*i)->save(st.sub); + writer.write(st); + } + + for(set::iterator i=routes.begin(); i!=routes.end(); ++i) + { + DataFile::Statement st("route"); + st.append((*i)->get_name()); + (*i)->save(st.sub); + writer.write(st); } } @@ -47,11 +81,11 @@ void Layout::check_links() for(set::iterator i=tracks.begin(); i!=tracks.end(); ++i) (*i)->break_links(); - set flext; + list flext; for(set::iterator i=tracks.begin(); i!=tracks.end(); ++i) { if((*i)->get_flex()) - flext.insert(*i); + flext.push_back(*i); else { for(set::iterator j=i; j!=tracks.end(); ++j) @@ -60,24 +94,65 @@ void Layout::check_links() } } - for(set::iterator i=flext.begin(); i!=flext.end(); ++i) + for(list::iterator i=flext.begin(); i!=flext.end(); ++i) for(set::iterator j=tracks.begin(); j!=tracks.end(); ++j) - if(j!=i) + if(*j!=*i) (*i)->snap_to(**j, true); } -void Layout::save(const string &fn) +void Layout::check_routes() { - IO::BufferedFile out(fn, IO::M_WRITE); - DataFile::Writer writer(out); - if(!base.empty()) - writer.write((DataFile::Statement("base"), base)); - for(set::iterator i=tracks.begin(); i!=tracks.end(); ++i) + for(set::iterator i=routes.begin(); i!=routes.end(); ++i) { - DataFile::Statement st("track"); - st.append((*i)->get_type().get_article_number()); - (*i)->save(st.sub); - writer.write(st); + // We must copy the turnout map, since adding tracks to the route will (temporarily) mess it up + const map turnouts = (*i)->get_turnouts(); + + Track *track = 0; + unsigned trk_route = 0; + for(set::const_iterator j=tracks.begin(); j!=tracks.end(); ++j) + { + map::const_iterator k = turnouts.find((*j)->get_turnout_id()); + if(k!=turnouts.end()) + { + track = *j; + trk_route = k->second; + break; + } + } + + (*i)->add_track(*track); + + const vector &eps = track->get_type().get_endpoints(); + unsigned ep = 0; + for(unsigned j=0; jtraverse(ep, trk_route); + if(out_ep<0) + break; + Track *next = track->get_links()[out_ep]; + if(!next || next == start) + break; + ep = next->get_endpoint_by_link(*track); + if(next->get_type().get_n_routes()>1) + { + map::const_iterator j = turnouts.find(next->get_turnout_id()); + if(j==turnouts.end()) + break; + trk_route = j->second; + } + else + trk_route = 0; + (*i)->add_track(*next); + track = next; + } } } @@ -86,17 +161,26 @@ Layout::Loader::Loader(Layout &l): DataFile::BasicLoader(l) { add("base", &Layout::base); + add("route", &Loader::route); add("track", &Loader::track); } void Layout::Loader::finish() { obj.check_links(); + obj.check_routes(); for(set::iterator i=obj.tracks.begin(); i!=obj.tracks.end(); ++i) (*i)->check_slope(); } +void Layout::Loader::route(const string &n) +{ + RefPtr rte = new Route(n); + load_sub(*rte); + obj.add_route(*rte.release()); +} + void Layout::Loader::track(unsigned art_nr) { TrackType &type = obj.catalogue.get_track(art_nr); diff --git a/source/libmarklin/layout.h b/source/libmarklin/layout.h index dd13925..2a1817f 100644 --- a/source/libmarklin/layout.h +++ b/source/libmarklin/layout.h @@ -26,18 +26,21 @@ public: Loader(Layout &); private: virtual void finish(); + void route(const std::string &); void track(unsigned); }; public: sigc::signal signal_track_added; sigc::signal signal_track_removed; + sigc::signal signal_route_added; + sigc::signal signal_route_removed; private: const Catalogue &catalogue; std::string base; std::set tracks; - //std::set routes; + std::set routes; public: Layout(const Catalogue &); @@ -48,8 +51,13 @@ public: const std::set &get_tracks() const { return tracks; } void add_track(Track &); void remove_track(Track &); - void check_links(); + void add_route(Route &); + const std::set &get_routes() const { return routes; } + void remove_route(Route &); void save(const std::string &); +private: + void check_links(); + void check_routes(); }; } // namespace Marklin diff --git a/source/libmarklin/route.cpp b/source/libmarklin/route.cpp index 7199fc9..fa2286c 100644 --- a/source/libmarklin/route.cpp +++ b/source/libmarklin/route.cpp @@ -1,14 +1,186 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa +Copyright © 2007-2009 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ +#include "track.h" +#include "tracktype.h" #include "route.h" +using namespace std; +using namespace Msp; + namespace Marklin { +Route::Route(const string &n): + name(n) +{ } + +int Route::get_turnout(unsigned id) const +{ + map::const_iterator i = turnouts.find(id); + if(i!=turnouts.end()) + return i->second; + return -1; +} + +void Route::add_track(const Track &trk) +{ + if(tracks.count(&trk)) + return; + + if(!tracks.empty()) + { + unsigned valid = check_validity(trk); + if(!(valid&1)) + throw Exception("Not linked to existing tracks"); + else if(!(valid&2)) + throw Exception("Branching routes not allowed"); + else if(!(valid&4)) + throw Exception("Route must be smooth"); + } + + tracks.insert(&trk); + update_turnouts(); +} + +void Route::add_tracks(const set &trks) +{ + set pending; + for(set::const_iterator i=trks.begin(); i!=trks.end(); ++i) + if(!tracks.count(*i)) + pending.insert(*i); + + while(!pending.empty()) + { + bool found = false; + for(set::const_iterator i=pending.begin(); i!=pending.end(); ++i) + if(tracks.empty() || check_validity(**i)==7) + { + tracks.insert(*i); + pending.erase(*i); + found = true; + break; + } + + if(!found) + throw Exception("Could not add all tracks to route"); + } + + update_turnouts(); +} + +void Route::save(list &st) const +{ + for(map::const_iterator i=turnouts.begin(); i!=turnouts.end(); ++i) + st.push_back((DataFile::Statement("turnout"), i->first, i->second)); +} + +void Route::update_turnouts() +{ + set found; + for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + if(unsigned tid=(*i)->get_turnout_id()) + { + found.insert(tid); + + const vector &endpoints = (*i)->get_type().get_endpoints(); + const vector &links = (*i)->get_links(); + + unsigned mask = 15; + for(unsigned j=0; jget_turnout_id()) + { + const Endpoint &ep = links[j]->get_type().get_endpoints()[links[j]->get_endpoint_by_link(**i)]; + int r = get_turnout(tid2); + if(r>=0 && !(ep.routes&(1<>=1, ++route) ; + turnouts[tid] = route; + } + else + turnouts[tid] = -1; + } + + for(map::iterator i=turnouts.begin(); i!=turnouts.end();) + { + if(!found.count(i->first)) + turnouts.erase(i++); + else + ++i; + } +} + +unsigned Route::check_validity(const Track &trk) const +{ + unsigned result = 4; + for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + int epi=(*i)->get_endpoint_by_link(trk); + if(epi>=0) + { + result |= 1; + const vector &endpoints = (*i)->get_type().get_endpoints(); + if(unsigned tid=(*i)->get_turnout_id()) + { + int r = get_turnout(tid); + if(r>=0) + { + if(endpoints[epi].routes&(1< &links = (*i)->get_links(); + int epj = -1; + for(unsigned k=0; k=0 && !(endpoints[epi].routes&endpoints[epj].routes)) + result &= 3; + } + } + } + else + result |= 2; + } + } + + return result; +} + + +Route::Loader::Loader(Route &r): + DataFile::BasicLoader(r) +{ + add("turnout", &Loader::turnout); +} +void Route::Loader::turnout(unsigned id, unsigned route) +{ + obj.turnouts[id] = route; +} } // namespace Marklin diff --git a/source/libmarklin/route.h b/source/libmarklin/route.h index a8e220d..6e69bba 100644 --- a/source/libmarklin/route.h +++ b/source/libmarklin/route.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2007-2008 Mikkosoft Productions, Mikko Rasa +Copyright © 2007-2009 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -11,6 +11,7 @@ Distributed under the GPL #include #include #include +#include namespace Marklin { @@ -19,17 +20,33 @@ class Turnout; class Route { +public: + class Loader: public Msp::DataFile::BasicLoader + { + public: + Loader(Route &); + private: + void turnout(unsigned, unsigned); + }; + private: std::string name; - std::set tracks; - std::map turnouts; + std::set tracks; + std::map turnouts; public: - Route(); - ~Route(); - - const std::map &get_turnouts() const { return turnouts; } - void add_track(Track *); + Route(const std::string &); + + const std::string &get_name() const { return name; } + int get_turnout(unsigned) const; + const std::map &get_turnouts() const { return turnouts; } + void add_track(const Track &); + void add_tracks(const std::set &); + const std::set &get_tracks() const { return tracks; } + void save(std::list &) const; +private: + void update_turnouts(); + unsigned check_validity(const Track &) const; }; } // namespace Marklin -- 2.43.0