1 #ifndef scr_coord_h 2 #define scr_coord_h 3 4 #include <assert.h> 5 #include "../dataobj/loadsave.h" 6 #include "../simtypes.h" 7 8 class koord; 9 10 // Screen coordinate type 11 typedef sint32 scr_coord_val; 12 13 // Rectangle relations 14 enum rect_relation_t { RECT_RELATION_INSIDE, RECT_RELATION_OVERLAP, RECT_RELATION_OUTSIDE }; 15 16 // Two dimensional coordinate type 17 class scr_coord 18 { 19 public: 20 scr_coord_val x; 21 scr_coord_val y; 22 23 // Constructors scr_coord()24 scr_coord( ) { x = y = 0; } scr_coord(scr_coord_val x_,scr_coord_val y_)25 scr_coord( scr_coord_val x_, scr_coord_val y_ ) { x = x_; y=y_; } 26 27 bool operator ==(const scr_coord& other) const { return ((x-other.x) | (y-other.y)) == 0; } 28 bool operator !=(const scr_coord& other) const { return !(other == *this ); } 29 const scr_coord operator +(const scr_coord& other ) const { return scr_coord( other.x + x, other.y + y); } 30 const scr_coord operator -(const scr_coord& other ) const { return scr_coord( x - other.x, y - other.y ); } 31 rdwr(loadsave_t * file)32 void rdwr(loadsave_t *file) 33 { 34 xml_tag_t k( file, "koord" ); 35 file->rdwr_long(x); 36 file->rdwr_long(y); 37 } 38 39 const scr_coord& operator +=(const scr_coord& other ) { 40 x += other.x; 41 y += other.y; 42 return *this; 43 } 44 45 const scr_coord& operator -=(const scr_coord& other ) { 46 x -= other.x; 47 y -= other.y; 48 return *this; 49 } 50 add_offset(scr_coord_val delta_x,scr_coord_val delta_y)51 void add_offset( scr_coord_val delta_x, scr_coord_val delta_y ) { 52 x += delta_x; 53 y += delta_y; 54 } 55 set(scr_coord_val x_par,scr_coord_val y_par)56 void set( scr_coord_val x_par, scr_coord_val y_par ) { 57 x = x_par; 58 y = y_par; 59 } 60 clip_lefttop(scr_coord scr_lefttop)61 inline void clip_lefttop( scr_coord scr_lefttop ) 62 { 63 if (x < scr_lefttop.x) { 64 x = scr_lefttop.x; 65 } 66 if (y < scr_lefttop.y) { 67 y = scr_lefttop.y; 68 } 69 } 70 clip_rightbottom(scr_coord scr_rightbottom)71 inline void clip_rightbottom( scr_coord scr_rightbottom ) 72 { 73 if (x > scr_rightbottom.x) { 74 x = scr_rightbottom.x; 75 } 76 if (y > scr_rightbottom.y) { 77 y = scr_rightbottom.y; 78 } 79 } 80 81 static const scr_coord invalid; 82 83 private: 84 // conversions to/from koord not allowed anymore 85 scr_coord( const koord); 86 operator koord() const; 87 }; 88 89 90 static inline scr_coord operator * (const scr_coord &k, const sint16 m) 91 { 92 return scr_coord(k.x * m, k.y * m); 93 } 94 95 96 static inline scr_coord operator / (const scr_coord &k, const sint16 m) 97 { 98 return scr_coord(k.x / m, k.y / m); 99 } 100 101 102 // Very simple scr_size struct. 103 class scr_size 104 { 105 public: 106 scr_coord_val w; 107 scr_coord_val h; 108 109 // Constructors scr_size()110 scr_size( ) { w = h = 0; } scr_size(scr_coord_val w_par,scr_coord_val h_par)111 scr_size( scr_coord_val w_par, scr_coord_val h_par) { w = w_par; h = h_par; } scr_size(const scr_size & size)112 scr_size( const scr_size& size ) { w = size.w; h=size.h; } 113 scr_coord()114 operator scr_coord() const { return scr_coord(w,h); } 115 116 bool operator ==(const scr_size& other) const { return ((w-other.w) | (h-other.h)) == 0; } 117 bool operator !=(const scr_size& other) const { return !(other == *this ); } 118 const scr_size operator +(const scr_size& other ) const { return scr_size( other.w + w, other.h + h); } 119 const scr_size operator -(const scr_size& other ) const { return scr_size( w - other.w, h - other.h ); } 120 const scr_size operator +(const scr_coord& other ) const { return scr_size( other.x + w, other.y + h); } 121 const scr_size operator -(const scr_coord& other ) const { return scr_size( w - other.x, h - other.y ); } 122 rdwr(loadsave_t * file)123 void rdwr(loadsave_t *file) 124 { 125 xml_tag_t k( file, "koord" ); 126 file->rdwr_long(w); 127 file->rdwr_long(h); 128 } 129 clip_lefttop(scr_coord scr_lefttop)130 inline void clip_lefttop( scr_coord scr_lefttop ) 131 { 132 if (w < scr_lefttop.x) { 133 w = scr_lefttop.x; 134 } 135 if (h < scr_lefttop.y) { 136 h = scr_lefttop.y; 137 } 138 } 139 clip_rightbottom(scr_coord scr_rightbottom)140 inline void clip_rightbottom( scr_coord scr_rightbottom ) 141 { 142 if (w > scr_rightbottom.x) { 143 w = scr_rightbottom.x; 144 } 145 if (h > scr_rightbottom.y) { 146 h = scr_rightbottom.y; 147 } 148 } 149 150 const scr_size& operator +=(const scr_size& other ) { 151 w += other.w; 152 h += other.h; 153 return *this; 154 } 155 156 const scr_size& operator -=(const scr_size& other ) { 157 w -= other.w; 158 h -= other.h; 159 return *this; 160 } 161 162 const scr_size& operator +=(const scr_coord& other ) { 163 w += other.x; 164 h += other.y; 165 return *this; 166 } 167 168 const scr_size& operator -=(const scr_coord& other ) { 169 w -= other.x; 170 h -= other.y; 171 return *this; 172 } 173 174 static const scr_size invalid; 175 176 static const scr_size inf; 177 private: 178 // conversions to/from koord not allowed anymore 179 operator koord() const; 180 }; 181 182 183 // Rectangle type 184 class scr_rect 185 { 186 public: 187 scr_coord_val x; 188 scr_coord_val y; 189 scr_coord_val w; 190 scr_coord_val h; 191 192 // to set it in one line ... set(scr_coord_val x_par,scr_coord_val y_par,scr_coord_val w_par,scr_coord_val h_par)193 void set( scr_coord_val x_par, scr_coord_val y_par, scr_coord_val w_par, scr_coord_val h_par ) { 194 x = x_par; 195 y = y_par; 196 w = w_par; 197 h = h_par; 198 } 199 200 // Constructors scr_rect()201 scr_rect() { set(0,0,0,0); } scr_rect(const scr_coord & pt)202 scr_rect( const scr_coord& pt ) { set( pt.x, pt.y, 0, 0 ); } scr_rect(const scr_coord & pt,scr_coord_val w,scr_coord_val h)203 scr_rect( const scr_coord& pt, scr_coord_val w, scr_coord_val h ) { set( pt.x, pt.y, w, h ); } scr_rect(const scr_coord & pt,const scr_size & sz)204 scr_rect( const scr_coord& pt, const scr_size& sz ) { set( pt.x, pt.y, sz.w, sz.h ); } scr_rect(scr_coord_val x,scr_coord_val y,scr_coord_val w,scr_coord_val h)205 scr_rect( scr_coord_val x, scr_coord_val y, scr_coord_val w, scr_coord_val h ) { set( x, y, w, h ); } scr_rect(scr_size size)206 scr_rect( scr_size size ) { w = size.w; h=size.h; x=0; y=0; } scr_rect(const scr_coord & point1,const scr_coord & point2)207 scr_rect( const scr_coord& point1, const scr_coord& point2 ) { set( point1.x, point1.y, point2.x-point1.x, point2.y-point1.y ); } 208 209 // Type cast operators scr_size()210 operator scr_size() const { return scr_size (w,h); } scr_coord()211 operator scr_coord() const { return scr_coord(x,y); } 212 213 // Unary operators 214 const scr_rect operator +(const scr_coord& other ) const { scr_rect rect(x + other.x, y + other.y, w, h ); return rect; } 215 const scr_rect operator -(const scr_coord& other ) const { scr_rect rect(x - other.x, y - other.y, w, h ); return rect; } 216 217 const scr_rect operator +(const scr_size& sz ) const { return scr_rect(x,y, w+sz.w, h+sz.h ); } 218 const scr_rect operator -(const scr_size& sz ) const { return scr_rect(x,y, w-sz.w, h-sz.h ); } 219 220 // Validation functions is_empty()221 bool is_empty() const { return (w|h) == 0; } is_valid()222 bool is_valid() const { return !is_empty(); } 223 224 // Helper functions get_pos()225 scr_coord get_pos() const { 226 return scr_coord( x, y ); 227 } 228 set_pos(const scr_coord point)229 void set_pos( const scr_coord point ) { 230 w = (x+w) - point.x; 231 h = (y+h) - point.y; 232 x = point.x; 233 y = point.y; 234 } 235 get_bottomright()236 const scr_coord get_bottomright() const { 237 return scr_coord( x+w, y+h ); 238 } 239 set_bottomright(const scr_coord & point)240 void set_bottomright( const scr_coord& point ) { 241 w = point.x - x; 242 h = point.y - y; 243 } 244 get_width()245 scr_coord_val get_width() const { return w; } 246 get_right()247 scr_coord_val get_right() const { return x+w; } 248 get_height()249 scr_coord_val get_height() const { return h; } 250 get_bottom()251 scr_coord_val get_bottom() const { return y+h; } 252 set_right(scr_coord_val right)253 void set_right(scr_coord_val right) { 254 w = right-x; 255 } 256 set_bottom(scr_coord_val bottom)257 void set_bottom(scr_coord_val bottom) { 258 h = bottom-y; 259 } 260 261 // now just working on two of the four coordinates move_to(scr_coord_val x_par,scr_coord_val y_par)262 void move_to( scr_coord_val x_par, scr_coord_val y_par ) { 263 x = x_par; 264 y = y_par; 265 } 266 move_to(const scr_coord & point)267 void move_to( const scr_coord& point ) { 268 move_to( point.x, point.y ); 269 } 270 271 // and the other two with the size get_size()272 const scr_size get_size() const { return scr_size( w, h ); } 273 set_size(const scr_size & sz)274 void set_size( const scr_size &sz ) { 275 w = sz.w; 276 h = sz.h; 277 } 278 set_size(scr_coord_val width,scr_coord_val height)279 void set_size( scr_coord_val width, scr_coord_val height) { 280 w = width; 281 h = height; 282 } 283 284 // add to left, right and top, bottom expand(scr_coord_val delta_x_par,scr_coord_val delta_y_par)285 void expand( scr_coord_val delta_x_par, scr_coord_val delta_y_par ) { 286 x -= delta_x_par; 287 y -= delta_y_par; 288 w += (delta_x_par<<1); 289 h += (delta_y_par<<1); 290 } 291 292 // Adjust rect to the bounding rect of this and rect. outer_bounds(const scr_rect & rect)293 void outer_bounds( const scr_rect &rect ) { 294 scr_coord pt( min(x,rect.x), min(y,rect.y) ); 295 w = max(x+w,rect.x+rect.w)-pt.x; 296 h = max(y+h,rect.y+rect.h)-pt.y; 297 x = pt.x; 298 y = pt.y; 299 } 300 301 // Enforce a positive width and height normalize()302 void normalize() { 303 if( w<0 ) { 304 x -= w; 305 w = -w; 306 } 307 if( h<0 ) { 308 y -= h; 309 h = -h; 310 } 311 } 312 313 // point in rect; border (x+w) is still counting as contained contains(const scr_coord & pt)314 bool contains( const scr_coord& pt ) const { 315 return ( x <= pt.x && x+w >= pt.x && y <=pt.y && y+h >= pt.y ); 316 } 317 318 // Now rect/rect functions: First check if rect is completely surrounded by this 319 // maybe surrounds would be a better name, but contains seems more consistent contains(const scr_rect & rect)320 bool contains( const scr_rect& rect ) const { 321 return ( x <= rect.x && x+w >= rect.x+rect.w && y <= rect.y && y+h >= rect.y+rect.h ); 322 } 323 is_overlapping(const scr_rect & rect)324 bool is_overlapping( const scr_rect &rect ) const { 325 return !( (get_bottomright().x < rect.x) || 326 (get_bottomright().y < rect.y) || 327 (rect.get_bottomright().x < x) || 328 (rect.get_bottomright().y < y) ); 329 } 330 relation(const scr_rect & rect)331 rect_relation_t relation( const scr_rect& rect ) const { 332 if( contains(rect) ) { 333 return RECT_RELATION_INSIDE; 334 } 335 else if( is_overlapping( rect ) ) { 336 return RECT_RELATION_OVERLAP; 337 } 338 return RECT_RELATION_OUTSIDE; 339 } 340 341 /* reduces the current rect to the overlapping area of two rect 342 * in case of no overlap the new size is negative 343 * (prissi: in my humble opinion this could rather return a new rect) 344 */ clip(const scr_rect clip_rect)345 void clip( const scr_rect clip_rect ) { 346 x = max(x, clip_rect.x); 347 set_right( min(x+w, clip_rect.x+clip_rect.w) ); 348 y = max(y, clip_rect.y); 349 set_bottom( min(y+h, clip_rect.y+clip_rect.h) ); 350 } 351 352 bool operator ==(const scr_rect& rect) const { 353 return ( (x-rect.x) | (y-rect.y) | (w-rect.w) | (h-rect.h) ) == 0; 354 } 355 356 bool operator !=(const scr_rect& rect_par) const { 357 return !(rect_par==*this); 358 } 359 private: 360 // conversions to/from koord not allowed anymore 361 scr_rect( const koord&); 362 operator koord() const; 363 }; 364 #endif 365