1 // -*- Mode: C++; tab-width:2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi:tw=80:et:ts=2:sts=2
3 //
4 // -----------------------------------------------------------------------
5 //
6 // This file is part of RLVM, a RealLive virtual machine clone.
7 //
8 // -----------------------------------------------------------------------
9 //
10 // Copyright (C) 2006, 2007 Elliot Glaysher
11 //
12 // This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation; either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
25 //
26 // -----------------------------------------------------------------------
27
28 #include <boost/archive/text_iarchive.hpp>
29 #include <boost/archive/text_oarchive.hpp>
30
31 // -----------------------------------------------------------------------
32
33 #include "systems/base/graphics_object.h"
34
35 #include <boost/serialization/scoped_ptr.hpp>
36 #include <boost/serialization/shared_ptr.hpp>
37
38 #include <algorithm>
39 #include <iostream>
40 #include <numeric>
41 #include <sstream>
42 #include <string>
43 #include <vector>
44
45 #include "systems/base/graphics_object_data.h"
46 #include "systems/base/object_mutator.h"
47 #include "utilities/exception.h"
48
49 const int DEFAULT_TEXT_SIZE = 14;
50 const int DEFAULT_TEXT_XSPACE = 0;
51 const int DEFAULT_TEXT_YSPACE = 0;
52 const int DEFAULT_TEXT_CHAR_COUNT = 0;
53 const int DEFAULT_TEXT_COLOUR = 0;
54 const int DEFAULT_TEXT_SHADOWCOLOUR = -1;
55
56 const int DEFAULT_DRIFT_COUNT = 1;
57 const int DEFAULT_DRIFT_USE_ANIMATION = 0;
58 const int DEFAULT_DRIFT_START_PATTERN = 0;
59 const int DEFAULT_DRIFT_END_PATTERN = 0;
60 const int DEFAULT_DRIFT_ANIMATION_TIME = 0;
61 const int DEFAULT_DRIFT_YSPEED = 1000;
62 const int DEFAULT_DRIFT_PERIOD = 0;
63 const int DEFAULT_DRIFT_AMPLITUDE = 0;
64 const int DEFAULT_DRIFT_USE_DRIFT = 0;
65 const int DEFAULT_DRIFT_UNKNOWN_PROP = 0;
66 const int DEFAULT_DRIFT_DRIFTSPEED = 0;
67 const Rect DEFAULT_DRIFT_AREA = Rect(Point(-1, -1), Size(-1, -1));
68
69 const int DEFAULT_DIGITS_VALUE = 0;
70 const int DEFAULT_DIGITS_DIGITS = 0;
71 const int DEFAULT_DIGITS_ZERO = 0;
72 const int DEFAULT_DIGITS_SIGN = 0;
73 const int DEFAULT_DIGITS_PACK = 0;
74 const int DEFAULT_DIGITS_SPACE = 0;
75
76 const int DEFAULT_BUTTON_IS_BUTTON = 0;
77 const int DEFAULT_BUTTON_ACTION = 0;
78 const int DEFAULT_BUTTON_SE = -1;
79 const int DEFAULT_BUTTON_GROUP = 0;
80 const int DEFAULT_BUTTON_NUMBER = 0;
81 const int DEFAULT_BUTTON_STATE = 0;
82 const bool DEFAULT_BUTTON_USING_OVERRIDES = 0;
83 const int DEFAULT_BUTTON_PATTERN_OVERRIDE = 0;
84 const int DEFAULT_BUTTON_X_OFFSET = 0;
85 const int DEFAULT_BUTTON_Y_OFFSET = 0;
86
87 const Rect EMPTY_CLIP = Rect(Point(0, 0), Size(-1, -1));
88
89 const boost::shared_ptr<GraphicsObject::Impl> GraphicsObject::s_empty_impl(
90 new GraphicsObject::Impl);
91
92 // -----------------------------------------------------------------------
93 // GraphicsObject::TextProperties
94 // -----------------------------------------------------------------------
TextProperties()95 GraphicsObject::Impl::TextProperties::TextProperties()
96 : text_size(DEFAULT_TEXT_SIZE),
97 xspace(DEFAULT_TEXT_XSPACE),
98 yspace(DEFAULT_TEXT_YSPACE),
99 char_count(DEFAULT_TEXT_CHAR_COUNT),
100 colour(DEFAULT_TEXT_COLOUR),
101 shadow_colour(DEFAULT_TEXT_SHADOWCOLOUR) {}
102
DriftProperties()103 GraphicsObject::Impl::DriftProperties::DriftProperties()
104 : count(DEFAULT_DRIFT_COUNT),
105 use_animation(DEFAULT_DRIFT_USE_ANIMATION),
106 start_pattern(DEFAULT_DRIFT_START_PATTERN),
107 end_pattern(DEFAULT_DRIFT_END_PATTERN),
108 total_animation_time_ms(DEFAULT_DRIFT_ANIMATION_TIME),
109 yspeed(DEFAULT_DRIFT_YSPEED),
110 period(DEFAULT_DRIFT_PERIOD),
111 amplitude(DEFAULT_DRIFT_AMPLITUDE),
112 use_drift(DEFAULT_DRIFT_USE_DRIFT),
113 unknown_drift_property(DEFAULT_DRIFT_UNKNOWN_PROP),
114 driftspeed(DEFAULT_DRIFT_DRIFTSPEED),
115 drift_area(DEFAULT_DRIFT_AREA) {}
116
DigitProperties()117 GraphicsObject::Impl::DigitProperties::DigitProperties()
118 : value(DEFAULT_DIGITS_VALUE),
119 digits(DEFAULT_DIGITS_DIGITS),
120 zero(DEFAULT_DIGITS_ZERO),
121 sign(DEFAULT_DIGITS_SIGN),
122 pack(DEFAULT_DIGITS_PACK),
123 space(DEFAULT_DIGITS_SPACE) {}
124
ButtonProperties()125 GraphicsObject::Impl::ButtonProperties::ButtonProperties()
126 : is_button(DEFAULT_BUTTON_IS_BUTTON),
127 action(DEFAULT_BUTTON_ACTION),
128 se(DEFAULT_BUTTON_SE),
129 group(DEFAULT_BUTTON_GROUP),
130 button_number(DEFAULT_BUTTON_NUMBER),
131 state(DEFAULT_BUTTON_STATE),
132 using_overides(DEFAULT_BUTTON_USING_OVERRIDES),
133 pattern_override(DEFAULT_BUTTON_PATTERN_OVERRIDE),
134 x_offset_override(DEFAULT_BUTTON_X_OFFSET),
135 y_offset_override(DEFAULT_BUTTON_Y_OFFSET) {}
136
137 // -----------------------------------------------------------------------
138 // GraphicsObject
139 // -----------------------------------------------------------------------
GraphicsObject()140 GraphicsObject::GraphicsObject() : impl_(s_empty_impl) {}
141
GraphicsObject(const GraphicsObject & rhs)142 GraphicsObject::GraphicsObject(const GraphicsObject& rhs) : impl_(rhs.impl_) {
143 if (rhs.object_data_) {
144 object_data_.reset(rhs.object_data_->Clone());
145 object_data_->set_owned_by(*this);
146 } else {
147 object_data_.reset();
148 }
149
150 for (auto const& mutator : rhs.object_mutators_)
151 object_mutators_.emplace_back(mutator->Clone());
152 }
153
~GraphicsObject()154 GraphicsObject::~GraphicsObject() { DeleteObjectMutators(); }
155
operator =(const GraphicsObject & obj)156 GraphicsObject& GraphicsObject::operator=(const GraphicsObject& obj) {
157 DeleteObjectMutators();
158 impl_ = obj.impl_;
159
160 if (obj.object_data_) {
161 object_data_.reset(obj.object_data_->Clone());
162 object_data_->set_owned_by(*this);
163 } else {
164 object_data_.reset();
165 }
166
167 for (auto const& mutator : obj.object_mutators_)
168 object_mutators_.emplace_back(mutator->Clone());
169
170 return *this;
171 }
172
SetObjectData(GraphicsObjectData * obj)173 void GraphicsObject::SetObjectData(GraphicsObjectData* obj) {
174 object_data_.reset(obj);
175 object_data_->set_owned_by(*this);
176 }
177
SetVisible(const int in)178 void GraphicsObject::SetVisible(const int in) {
179 MakeImplUnique();
180 impl_->visible_ = in;
181 }
182
SetX(const int x)183 void GraphicsObject::SetX(const int x) {
184 MakeImplUnique();
185 impl_->x_ = x;
186 }
187
SetY(const int y)188 void GraphicsObject::SetY(const int y) {
189 MakeImplUnique();
190 impl_->y_ = y;
191 }
192
GetXAdjustmentSum() const193 int GraphicsObject::GetXAdjustmentSum() const {
194 return std::accumulate(impl_->adjust_x_, impl_->adjust_x_ + 8, 0);
195 }
196
SetXAdjustment(int idx,int x)197 void GraphicsObject::SetXAdjustment(int idx, int x) {
198 MakeImplUnique();
199 impl_->adjust_x_[idx] = x;
200 }
201
GetYAdjustmentSum() const202 int GraphicsObject::GetYAdjustmentSum() const {
203 return std::accumulate(impl_->adjust_y_, impl_->adjust_y_ + 8, 0);
204 }
205
SetYAdjustment(int idx,int y)206 void GraphicsObject::SetYAdjustment(int idx, int y) {
207 MakeImplUnique();
208 impl_->adjust_y_[idx] = y;
209 }
210
SetVert(const int vert)211 void GraphicsObject::SetVert(const int vert) {
212 MakeImplUnique();
213 impl_->whatever_adjust_vert_operates_on_ = vert;
214 }
215
SetOriginX(const int x)216 void GraphicsObject::SetOriginX(const int x) {
217 MakeImplUnique();
218 impl_->origin_x_ = x;
219 }
220
SetOriginY(const int y)221 void GraphicsObject::SetOriginY(const int y) {
222 MakeImplUnique();
223 impl_->origin_y_ = y;
224 }
225
SetRepOriginX(const int x)226 void GraphicsObject::SetRepOriginX(const int x) {
227 MakeImplUnique();
228 impl_->rep_origin_x_ = x;
229 }
230
SetRepOriginY(const int y)231 void GraphicsObject::SetRepOriginY(const int y) {
232 MakeImplUnique();
233 impl_->rep_origin_y_ = y;
234 }
235
SetWidth(const int in)236 void GraphicsObject::SetWidth(const int in) {
237 MakeImplUnique();
238 impl_->width_ = in;
239 }
240
SetHeight(const int in)241 void GraphicsObject::SetHeight(const int in) {
242 MakeImplUnique();
243 impl_->height_ = in;
244 }
245
SetHqWidth(const int in)246 void GraphicsObject::SetHqWidth(const int in) {
247 MakeImplUnique();
248 impl_->hq_width_ = in;
249 }
250
SetHqHeight(const int in)251 void GraphicsObject::SetHqHeight(const int in) {
252 MakeImplUnique();
253 impl_->hq_height_ = in;
254 }
255
GetWidthScaleFactor() const256 float GraphicsObject::GetWidthScaleFactor() const {
257 return (impl_->width_ / 100.0f) * (impl_->hq_width_ / 1000.0f);
258 }
259
GetHeightScaleFactor() const260 float GraphicsObject::GetHeightScaleFactor() const {
261 return (impl_->height_ / 100.0f) * (impl_->hq_height_ / 1000.0f);
262 }
263
SetRotation(const int in)264 void GraphicsObject::SetRotation(const int in) {
265 MakeImplUnique();
266 impl_->rotation_ = in;
267 }
268
PixelWidth() const269 int GraphicsObject::PixelWidth() const {
270 // Calculate out the pixel width of the current object taking in the
271 // width() scaling.
272 if (has_object_data())
273 return object_data_->PixelWidth(*this);
274 else
275 return 0;
276 }
277
PixelHeight() const278 int GraphicsObject::PixelHeight() const {
279 if (has_object_data())
280 return object_data_->PixelHeight(*this);
281 else
282 return 0;
283 }
284
GetPattNo() const285 int GraphicsObject::GetPattNo() const {
286 if (GetButtonUsingOverides())
287 return GetButtonPatternOverride();
288
289 return impl_->patt_no_;
290 }
291
SetPattNo(const int in)292 void GraphicsObject::SetPattNo(const int in) {
293 MakeImplUnique();
294 impl_->patt_no_ = in;
295 }
296
SetMono(const int in)297 void GraphicsObject::SetMono(const int in) {
298 MakeImplUnique();
299 impl_->mono_ = in;
300 }
301
SetInvert(const int in)302 void GraphicsObject::SetInvert(const int in) {
303 MakeImplUnique();
304 impl_->invert_ = in;
305 }
306
SetLight(const int in)307 void GraphicsObject::SetLight(const int in) {
308 MakeImplUnique();
309 impl_->light_ = in;
310 }
311
SetTint(const RGBColour & colour)312 void GraphicsObject::SetTint(const RGBColour& colour) {
313 MakeImplUnique();
314 impl_->tint_ = colour;
315 }
316
SetTintRed(const int in)317 void GraphicsObject::SetTintRed(const int in) {
318 MakeImplUnique();
319 impl_->tint_.set_red(in);
320 }
321
SetTintGreen(const int in)322 void GraphicsObject::SetTintGreen(const int in) {
323 MakeImplUnique();
324 impl_->tint_.set_green(in);
325 }
326
SetTintBlue(const int in)327 void GraphicsObject::SetTintBlue(const int in) {
328 MakeImplUnique();
329 impl_->tint_.set_blue(in);
330 }
331
SetColour(const RGBAColour & colour)332 void GraphicsObject::SetColour(const RGBAColour& colour) {
333 MakeImplUnique();
334 impl_->colour_ = colour;
335 }
336
SetColourRed(const int in)337 void GraphicsObject::SetColourRed(const int in) {
338 MakeImplUnique();
339 impl_->colour_.set_red(in);
340 }
341
SetColourGreen(const int in)342 void GraphicsObject::SetColourGreen(const int in) {
343 MakeImplUnique();
344 impl_->colour_.set_green(in);
345 }
346
SetColourBlue(const int in)347 void GraphicsObject::SetColourBlue(const int in) {
348 MakeImplUnique();
349 impl_->colour_.set_blue(in);
350 }
351
SetColourLevel(const int in)352 void GraphicsObject::SetColourLevel(const int in) {
353 MakeImplUnique();
354 impl_->colour_.set_alpha(in);
355 }
356
SetCompositeMode(const int in)357 void GraphicsObject::SetCompositeMode(const int in) {
358 MakeImplUnique();
359 impl_->composite_mode_ = in;
360 }
361
SetScrollRateX(const int x)362 void GraphicsObject::SetScrollRateX(const int x) {
363 MakeImplUnique();
364 impl_->scroll_rate_x_ = x;
365 }
366
SetScrollRateY(const int y)367 void GraphicsObject::SetScrollRateY(const int y) {
368 MakeImplUnique();
369 impl_->scroll_rate_y_ = y;
370 }
371
SetZOrder(const int in)372 void GraphicsObject::SetZOrder(const int in) {
373 MakeImplUnique();
374 impl_->z_order_ = in;
375 }
376
SetZLayer(const int in)377 void GraphicsObject::SetZLayer(const int in) {
378 MakeImplUnique();
379 impl_->z_layer_ = in;
380 }
381
SetZDepth(const int in)382 void GraphicsObject::SetZDepth(const int in) {
383 MakeImplUnique();
384 impl_->z_depth_ = in;
385 }
386
GetComputedAlpha() const387 int GraphicsObject::GetComputedAlpha() const {
388 int alpha = impl_->alpha_;
389 for (int i = 0; i < 8; ++i)
390 alpha = (alpha * impl_->adjust_alpha_[i]) / 255;
391 return alpha;
392 }
393
SetAlpha(const int alpha)394 void GraphicsObject::SetAlpha(const int alpha) {
395 MakeImplUnique();
396 impl_->alpha_ = alpha;
397 }
398
SetAlphaAdjustment(int idx,int alpha)399 void GraphicsObject::SetAlphaAdjustment(int idx, int alpha) {
400 MakeImplUnique();
401 impl_->adjust_alpha_[idx] = alpha;
402 }
403
ClearClipRect()404 void GraphicsObject::ClearClipRect() {
405 MakeImplUnique();
406 impl_->clip_ = EMPTY_CLIP;
407 }
408
SetClipRect(const Rect & rect)409 void GraphicsObject::SetClipRect(const Rect& rect) {
410 MakeImplUnique();
411 impl_->clip_ = rect;
412 }
413
ClearOwnClipRect()414 void GraphicsObject::ClearOwnClipRect() {
415 MakeImplUnique();
416 impl_->own_clip_ = EMPTY_CLIP;
417 }
418
SetOwnClipRect(const Rect & rect)419 void GraphicsObject::SetOwnClipRect(const Rect& rect) {
420 MakeImplUnique();
421 impl_->own_clip_ = rect;
422 }
423
GetObjectData()424 GraphicsObjectData& GraphicsObject::GetObjectData() {
425 if (object_data_) {
426 return *object_data_;
427 } else {
428 throw rlvm::Exception("null object data");
429 }
430 }
431
SetWipeCopy(const int wipe_copy)432 void GraphicsObject::SetWipeCopy(const int wipe_copy) {
433 MakeImplUnique();
434 impl_->wipe_copy_ = wipe_copy;
435 }
436
SetTextText(const std::string & utf8str)437 void GraphicsObject::SetTextText(const std::string& utf8str) {
438 MakeImplUnique();
439 impl_->MakeSureHaveTextProperties();
440 impl_->text_properties_->value = utf8str;
441 }
442
GetTextText() const443 const std::string& GraphicsObject::GetTextText() const {
444 static const std::string empty = "";
445
446 if (impl_->text_properties_)
447 return impl_->text_properties_->value;
448 else
449 return empty;
450 }
451
GetTextSize() const452 int GraphicsObject::GetTextSize() const {
453 if (impl_->text_properties_)
454 return impl_->text_properties_->text_size;
455 else
456 return DEFAULT_TEXT_SIZE;
457 }
458
GetTextXSpace() const459 int GraphicsObject::GetTextXSpace() const {
460 if (impl_->text_properties_)
461 return impl_->text_properties_->xspace;
462 else
463 return DEFAULT_TEXT_XSPACE;
464 }
465
GetTextYSpace() const466 int GraphicsObject::GetTextYSpace() const {
467 if (impl_->text_properties_)
468 return impl_->text_properties_->yspace;
469 else
470 return DEFAULT_TEXT_YSPACE;
471 }
472
GetTextCharCount() const473 int GraphicsObject::GetTextCharCount() const {
474 if (impl_->text_properties_)
475 return impl_->text_properties_->char_count;
476 else
477 return DEFAULT_TEXT_CHAR_COUNT;
478 }
479
GetTextColour() const480 int GraphicsObject::GetTextColour() const {
481 if (impl_->text_properties_)
482 return impl_->text_properties_->colour;
483 else
484 return DEFAULT_TEXT_COLOUR;
485 }
486
GetTextShadowColour() const487 int GraphicsObject::GetTextShadowColour() const {
488 if (impl_->text_properties_)
489 return impl_->text_properties_->shadow_colour;
490 else
491 return DEFAULT_TEXT_SHADOWCOLOUR;
492 }
493
SetTextOps(int size,int xspace,int yspace,int char_count,int colour,int shadow)494 void GraphicsObject::SetTextOps(int size,
495 int xspace,
496 int yspace,
497 int char_count,
498 int colour,
499 int shadow) {
500 MakeImplUnique();
501
502 impl_->MakeSureHaveTextProperties();
503 impl_->text_properties_->text_size = size;
504 impl_->text_properties_->xspace = xspace;
505 impl_->text_properties_->yspace = yspace;
506 impl_->text_properties_->char_count = char_count;
507 impl_->text_properties_->colour = colour;
508 impl_->text_properties_->shadow_colour = shadow;
509 }
510
SetDriftOpts(int count,int use_animation,int start_pattern,int end_pattern,int total_animation_time_ms,int yspeed,int period,int amplitude,int use_drift,int unknown_drift_property,int driftspeed,Rect driftarea)511 void GraphicsObject::SetDriftOpts(int count,
512 int use_animation,
513 int start_pattern,
514 int end_pattern,
515 int total_animation_time_ms,
516 int yspeed,
517 int period,
518 int amplitude,
519 int use_drift,
520 int unknown_drift_property,
521 int driftspeed,
522 Rect driftarea) {
523 MakeImplUnique();
524
525 impl_->MakeSureHaveDriftProperties();
526 impl_->drift_properties_->count = count;
527 impl_->drift_properties_->use_animation = use_animation;
528 impl_->drift_properties_->start_pattern = start_pattern;
529 impl_->drift_properties_->end_pattern = end_pattern;
530 impl_->drift_properties_->total_animation_time_ms = total_animation_time_ms;
531 impl_->drift_properties_->yspeed = yspeed;
532 impl_->drift_properties_->period = period;
533 impl_->drift_properties_->amplitude = amplitude;
534 impl_->drift_properties_->use_drift = use_drift;
535 impl_->drift_properties_->unknown_drift_property = unknown_drift_property;
536 impl_->drift_properties_->driftspeed = driftspeed;
537 impl_->drift_properties_->drift_area = driftarea;
538 }
539
GetDriftParticleCount() const540 int GraphicsObject::GetDriftParticleCount() const {
541 if (impl_->drift_properties_)
542 return impl_->drift_properties_->count;
543 else
544 return DEFAULT_DRIFT_COUNT;
545 }
546
GetDriftUseAnimation() const547 int GraphicsObject::GetDriftUseAnimation() const {
548 if (impl_->drift_properties_)
549 return impl_->drift_properties_->use_animation;
550 else
551 return DEFAULT_DRIFT_USE_ANIMATION;
552 }
553
GetDriftStartPattern() const554 int GraphicsObject::GetDriftStartPattern() const {
555 if (impl_->drift_properties_)
556 return impl_->drift_properties_->start_pattern;
557 else
558 return DEFAULT_DRIFT_START_PATTERN;
559 }
560
GetDriftEndPattern() const561 int GraphicsObject::GetDriftEndPattern() const {
562 if (impl_->drift_properties_)
563 return impl_->drift_properties_->end_pattern;
564 else
565 return DEFAULT_DRIFT_END_PATTERN;
566 }
567
GetDriftAnimationTime() const568 int GraphicsObject::GetDriftAnimationTime() const {
569 if (impl_->drift_properties_)
570 return impl_->drift_properties_->total_animation_time_ms;
571 else
572 return DEFAULT_DRIFT_ANIMATION_TIME;
573 }
574
GetDriftYSpeed() const575 int GraphicsObject::GetDriftYSpeed() const {
576 if (impl_->drift_properties_)
577 return impl_->drift_properties_->yspeed;
578 else
579 return DEFAULT_DRIFT_YSPEED;
580 }
581
GetDriftPeriod() const582 int GraphicsObject::GetDriftPeriod() const {
583 if (impl_->drift_properties_)
584 return impl_->drift_properties_->period;
585 else
586 return DEFAULT_DRIFT_PERIOD;
587 }
588
GetDriftAmplitude() const589 int GraphicsObject::GetDriftAmplitude() const {
590 if (impl_->drift_properties_)
591 return impl_->drift_properties_->amplitude;
592 else
593 return DEFAULT_DRIFT_AMPLITUDE;
594 }
595
GetDriftUseDrift() const596 int GraphicsObject::GetDriftUseDrift() const {
597 if (impl_->drift_properties_)
598 return impl_->drift_properties_->use_drift;
599 else
600 return DEFAULT_DRIFT_USE_DRIFT;
601 }
602
GetDriftUnknown() const603 int GraphicsObject::GetDriftUnknown() const {
604 if (impl_->drift_properties_)
605 return impl_->drift_properties_->unknown_drift_property;
606 else
607 return DEFAULT_DRIFT_UNKNOWN_PROP;
608 }
609
GetDriftDriftSpeed() const610 int GraphicsObject::GetDriftDriftSpeed() const {
611 if (impl_->drift_properties_)
612 return impl_->drift_properties_->driftspeed;
613 else
614 return DEFAULT_DRIFT_UNKNOWN_PROP;
615 }
616
GetDriftArea() const617 Rect GraphicsObject::GetDriftArea() const {
618 if (impl_->drift_properties_)
619 return impl_->drift_properties_->drift_area;
620 else
621 return Rect();
622 }
623
SetDigitValue(int value)624 void GraphicsObject::SetDigitValue(int value) {
625 MakeImplUnique();
626 impl_->MakeSureHaveDigitProperties();
627 impl_->digit_properties_->value = value;
628 }
629
SetDigitOpts(int digits,int zero,int sign,int pack,int space)630 void GraphicsObject::SetDigitOpts(int digits,
631 int zero,
632 int sign,
633 int pack,
634 int space) {
635 MakeImplUnique();
636
637 impl_->MakeSureHaveDigitProperties();
638 impl_->digit_properties_->digits = digits;
639 impl_->digit_properties_->zero = zero;
640 impl_->digit_properties_->sign = sign;
641 impl_->digit_properties_->pack = pack;
642 impl_->digit_properties_->space = space;
643 }
644
GetDigitValue() const645 int GraphicsObject::GetDigitValue() const {
646 if (impl_->digit_properties_)
647 return impl_->digit_properties_->value;
648 else
649 return DEFAULT_DIGITS_VALUE;
650 }
651
GetDigitDigits() const652 int GraphicsObject::GetDigitDigits() const {
653 if (impl_->digit_properties_)
654 return impl_->digit_properties_->digits;
655 else
656 return DEFAULT_DIGITS_DIGITS;
657 }
658
GetDigitZero() const659 int GraphicsObject::GetDigitZero() const {
660 if (impl_->digit_properties_)
661 return impl_->digit_properties_->zero;
662 else
663 return DEFAULT_DIGITS_ZERO;
664 }
665
GetDigitSign() const666 int GraphicsObject::GetDigitSign() const {
667 if (impl_->digit_properties_)
668 return impl_->digit_properties_->sign;
669 else
670 return DEFAULT_DIGITS_SIGN;
671 }
672
GetDigitPack() const673 int GraphicsObject::GetDigitPack() const {
674 if (impl_->digit_properties_)
675 return impl_->digit_properties_->pack;
676 else
677 return DEFAULT_DIGITS_PACK;
678 }
679
GetDigitSpace() const680 int GraphicsObject::GetDigitSpace() const {
681 if (impl_->digit_properties_)
682 return impl_->digit_properties_->space;
683 else
684 return DEFAULT_DIGITS_SPACE;
685 }
686
SetButtonOpts(int action,int se,int group,int button_number)687 void GraphicsObject::SetButtonOpts(int action,
688 int se,
689 int group,
690 int button_number) {
691 MakeImplUnique();
692 impl_->MakeSureHaveButtonProperties();
693 impl_->button_properties_->is_button = true;
694 impl_->button_properties_->action = action;
695 impl_->button_properties_->se = se;
696 impl_->button_properties_->group = group;
697 impl_->button_properties_->button_number = button_number;
698 }
699
SetButtonState(int state)700 void GraphicsObject::SetButtonState(int state) {
701 MakeImplUnique();
702 impl_->MakeSureHaveButtonProperties();
703 impl_->button_properties_->state = state;
704 }
705
IsButton() const706 int GraphicsObject::IsButton() const {
707 if (impl_->button_properties_)
708 return impl_->button_properties_->is_button;
709 else
710 return DEFAULT_BUTTON_IS_BUTTON;
711 }
712
GetButtonAction() const713 int GraphicsObject::GetButtonAction() const {
714 if (impl_->button_properties_)
715 return impl_->button_properties_->action;
716 else
717 return DEFAULT_BUTTON_ACTION;
718 }
719
GetButtonSe() const720 int GraphicsObject::GetButtonSe() const {
721 if (impl_->button_properties_)
722 return impl_->button_properties_->se;
723 else
724 return DEFAULT_BUTTON_SE;
725 }
726
GetButtonGroup() const727 int GraphicsObject::GetButtonGroup() const {
728 if (impl_->button_properties_)
729 return impl_->button_properties_->group;
730 else
731 return DEFAULT_BUTTON_GROUP;
732 }
733
GetButtonNumber() const734 int GraphicsObject::GetButtonNumber() const {
735 if (impl_->button_properties_)
736 return impl_->button_properties_->button_number;
737 else
738 return DEFAULT_BUTTON_NUMBER;
739 }
740
GetButtonState() const741 int GraphicsObject::GetButtonState() const {
742 if (impl_->button_properties_)
743 return impl_->button_properties_->state;
744 else
745 return DEFAULT_BUTTON_STATE;
746 }
747
SetButtonOverrides(int override_pattern,int override_x_offset,int override_y_offset)748 void GraphicsObject::SetButtonOverrides(int override_pattern,
749 int override_x_offset,
750 int override_y_offset) {
751 MakeImplUnique();
752 impl_->MakeSureHaveButtonProperties();
753 impl_->button_properties_->using_overides = true;
754 impl_->button_properties_->pattern_override = override_pattern;
755 impl_->button_properties_->x_offset_override = override_x_offset;
756 impl_->button_properties_->y_offset_override = override_y_offset;
757 }
758
ClearButtonOverrides()759 void GraphicsObject::ClearButtonOverrides() {
760 MakeImplUnique();
761 impl_->MakeSureHaveButtonProperties();
762 impl_->button_properties_->using_overides = false;
763 }
764
GetButtonUsingOverides() const765 bool GraphicsObject::GetButtonUsingOverides() const {
766 if (impl_->button_properties_)
767 return impl_->button_properties_->using_overides;
768 else
769 return DEFAULT_BUTTON_USING_OVERRIDES;
770 }
771
GetButtonPatternOverride() const772 int GraphicsObject::GetButtonPatternOverride() const {
773 if (impl_->button_properties_)
774 return impl_->button_properties_->pattern_override;
775 else
776 return DEFAULT_BUTTON_PATTERN_OVERRIDE;
777 }
778
GetButtonXOffsetOverride() const779 int GraphicsObject::GetButtonXOffsetOverride() const {
780 if (impl_->button_properties_)
781 return impl_->button_properties_->x_offset_override;
782 else
783 return DEFAULT_BUTTON_X_OFFSET;
784 }
785
GetButtonYOffsetOverride() const786 int GraphicsObject::GetButtonYOffsetOverride() const {
787 if (impl_->button_properties_)
788 return impl_->button_properties_->y_offset_override;
789 else
790 return DEFAULT_BUTTON_Y_OFFSET;
791 }
792
AddObjectMutator(std::unique_ptr<ObjectMutator> mutator)793 void GraphicsObject::AddObjectMutator(std::unique_ptr<ObjectMutator> mutator) {
794 MakeImplUnique();
795
796 // If there's a currently running mutator that matches the incoming mutator,
797 // we ignore the incoming mutator. Kud Wafter's ED relies on this behavior.
798 for (std::unique_ptr<ObjectMutator>& mutator_ptr : object_mutators_) {
799 if (mutator_ptr->OperationMatches(mutator->repr(), mutator->name())) {
800 return;
801 }
802 }
803
804 object_mutators_.push_back(std::move(mutator));
805 }
806
IsMutatorRunningMatching(int repno,const std::string & name)807 bool GraphicsObject::IsMutatorRunningMatching(int repno,
808 const std::string& name) {
809 for (auto const& mutator : object_mutators_) {
810 if (mutator->OperationMatches(repno, name))
811 return true;
812 }
813
814 return false;
815 }
816
EndObjectMutatorMatching(RLMachine & machine,int repno,const std::string & name,int speedup)817 void GraphicsObject::EndObjectMutatorMatching(RLMachine& machine,
818 int repno,
819 const std::string& name,
820 int speedup) {
821 if (speedup == 0) {
822 std::vector<std::unique_ptr<ObjectMutator>>::iterator it =
823 object_mutators_.begin();
824 while (it != object_mutators_.end()) {
825 if ((*it)->OperationMatches(repno, name)) {
826 (*it)->SetToEnd(machine, *this);
827 it = object_mutators_.erase(it);
828 } else {
829 ++it;
830 }
831 }
832 } else if (speedup == 1) {
833 // This is explicitly a noop.
834 } else {
835 std::cerr << "Warning: We only do immediate endings in "
836 << "EndObjectMutatorMatching(). Unsupported speedup " << speedup
837 << std::endl;
838 }
839 }
840
GetMutatorNames() const841 std::vector<std::string> GraphicsObject::GetMutatorNames() const {
842 std::vector<std::string> names;
843
844 for (auto& mutator : object_mutators_) {
845 std::ostringstream oss;
846 oss << mutator->name();
847 if (mutator->repr() != -1)
848 oss << "/" << mutator->repr();
849 names.push_back(oss.str());
850 }
851
852 return names;
853 }
854
MakeImplUnique()855 void GraphicsObject::MakeImplUnique() {
856 if (!impl_.unique()) {
857 impl_.reset(new Impl(*impl_));
858 }
859 }
860
DeleteObjectMutators()861 void GraphicsObject::DeleteObjectMutators() {
862 object_mutators_.clear();
863 }
864
Render(int objNum,const GraphicsObject * parent,std::ostream * tree)865 void GraphicsObject::Render(int objNum,
866 const GraphicsObject* parent,
867 std::ostream* tree) {
868 if (object_data_ && visible()) {
869 if (tree) {
870 *tree << "Object #" << objNum << ":" << std::endl;
871 }
872
873 object_data_->Render(*this, parent, tree);
874 }
875 }
876
FreeObjectData()877 void GraphicsObject::FreeObjectData() {
878 object_data_.reset();
879 DeleteObjectMutators();
880 }
881
InitializeParams()882 void GraphicsObject::InitializeParams() {
883 impl_ = s_empty_impl;
884 DeleteObjectMutators();
885 }
886
FreeDataAndInitializeParams()887 void GraphicsObject::FreeDataAndInitializeParams() {
888 object_data_.reset();
889 impl_ = s_empty_impl;
890 DeleteObjectMutators();
891 }
892
Execute(RLMachine & machine)893 void GraphicsObject::Execute(RLMachine& machine) {
894 if (object_data_) {
895 object_data_->Execute(machine);
896 }
897
898 // Run each mutator. If it returns true, remove it.
899 std::vector<std::unique_ptr<ObjectMutator>>::iterator it =
900 object_mutators_.begin();
901 while (it != object_mutators_.end()) {
902 if ((**it)(machine, *this)) {
903 it = object_mutators_.erase(it);
904 } else {
905 ++it;
906 }
907 }
908 }
909
910 template <class Archive>
serialize(Archive & ar,unsigned int version)911 void GraphicsObject::serialize(Archive& ar, unsigned int version) {
912 ar& impl_& object_data_;
913 }
914
915 // -----------------------------------------------------------------------
916
917 template void GraphicsObject::serialize<boost::archive::text_oarchive>(
918 boost::archive::text_oarchive& ar,
919 unsigned int version);
920
921 template void GraphicsObject::serialize<boost::archive::text_iarchive>(
922 boost::archive::text_iarchive& ar,
923 unsigned int version);
924
925 // -----------------------------------------------------------------------
926 // GraphicsObject::Impl
927 // -----------------------------------------------------------------------
Impl()928 GraphicsObject::Impl::Impl()
929 : visible_(false),
930 x_(0),
931 y_(0),
932 whatever_adjust_vert_operates_on_(0),
933 origin_x_(0),
934 origin_y_(0),
935 rep_origin_x_(0),
936 rep_origin_y_(0),
937
938 // Width and height are percentages
939 width_(100),
940 height_(100),
941 hq_width_(1000),
942 hq_height_(1000),
943 rotation_(0),
944 patt_no_(0),
945 alpha_(255),
946 clip_(EMPTY_CLIP),
947 own_clip_(EMPTY_CLIP),
948 mono_(0),
949 invert_(0),
950 light_(0),
951 // Do the rest later.
952 tint_(RGBColour::Black()),
953 colour_(RGBAColour::Clear()),
954 composite_mode_(0),
955 scroll_rate_x_(0),
956 scroll_rate_y_(0),
957 z_order_(0),
958 z_layer_(0),
959 z_depth_(0),
960 wipe_copy_(0) {
961 // Regretfully, we can't do this in the initializer list.
962 std::fill(adjust_x_, adjust_x_ + 8, 0);
963 std::fill(adjust_y_, adjust_y_ + 8, 0);
964 std::fill(adjust_alpha_, adjust_alpha_ + 8, 255);
965 }
966
Impl(const Impl & rhs)967 GraphicsObject::Impl::Impl(const Impl& rhs)
968 : visible_(rhs.visible_),
969 x_(rhs.x_),
970 y_(rhs.y_),
971 whatever_adjust_vert_operates_on_(rhs.whatever_adjust_vert_operates_on_),
972 origin_x_(rhs.origin_x_),
973 origin_y_(rhs.origin_y_),
974 rep_origin_x_(rhs.rep_origin_x_),
975 rep_origin_y_(rhs.rep_origin_y_),
976 width_(rhs.width_),
977 height_(rhs.height_),
978 hq_width_(rhs.hq_width_),
979 hq_height_(rhs.hq_height_),
980 rotation_(rhs.rotation_),
981 patt_no_(rhs.patt_no_),
982 alpha_(rhs.alpha_),
983 clip_(rhs.clip_),
984 own_clip_(rhs.own_clip_),
985 mono_(rhs.mono_),
986 invert_(rhs.invert_),
987 light_(rhs.light_),
988 tint_(rhs.tint_),
989 colour_(rhs.colour_),
990 composite_mode_(rhs.composite_mode_),
991 scroll_rate_x_(rhs.scroll_rate_x_),
992 scroll_rate_y_(rhs.scroll_rate_y_),
993 z_order_(rhs.z_order_),
994 z_layer_(rhs.z_layer_),
995 z_depth_(rhs.z_depth_),
996 wipe_copy_(0) {
997 if (rhs.text_properties_)
998 text_properties_.reset(new TextProperties(*rhs.text_properties_));
999 if (rhs.drift_properties_)
1000 drift_properties_.reset(new DriftProperties(*rhs.drift_properties_));
1001 if (rhs.digit_properties_)
1002 digit_properties_.reset(new DigitProperties(*rhs.digit_properties_));
1003 if (rhs.button_properties_)
1004 button_properties_.reset(new ButtonProperties(*rhs.button_properties_));
1005
1006 std::copy(rhs.adjust_x_, rhs.adjust_x_ + 8, adjust_x_);
1007 std::copy(rhs.adjust_y_, rhs.adjust_y_ + 8, adjust_y_);
1008 std::copy(rhs.adjust_alpha_, rhs.adjust_alpha_ + 8, adjust_alpha_);
1009 }
1010
~Impl()1011 GraphicsObject::Impl::~Impl() {}
1012
operator =(const GraphicsObject::Impl & rhs)1013 GraphicsObject::Impl& GraphicsObject::Impl::operator=(
1014 const GraphicsObject::Impl& rhs) {
1015 if (this != &rhs) {
1016 visible_ = rhs.visible_;
1017 x_ = rhs.x_;
1018 y_ = rhs.y_;
1019
1020 std::copy(rhs.adjust_x_, rhs.adjust_x_ + 8, adjust_x_);
1021 std::copy(rhs.adjust_y_, rhs.adjust_y_ + 8, adjust_y_);
1022 std::copy(rhs.adjust_alpha_, rhs.adjust_alpha_ + 8, adjust_alpha_);
1023
1024 whatever_adjust_vert_operates_on_ = rhs.whatever_adjust_vert_operates_on_;
1025 origin_x_ = rhs.origin_x_;
1026 origin_y_ = rhs.origin_y_;
1027 rep_origin_x_ = rhs.rep_origin_x_;
1028 rep_origin_y_ = rhs.rep_origin_y_;
1029 width_ = rhs.width_;
1030 height_ = rhs.height_;
1031 hq_width_ = rhs.hq_width_;
1032 hq_height_ = rhs.hq_height_;
1033 rotation_ = rhs.rotation_;
1034
1035 patt_no_ = rhs.patt_no_;
1036 alpha_ = rhs.alpha_;
1037 clip_ = rhs.clip_;
1038 own_clip_ = rhs.own_clip_;
1039 mono_ = rhs.mono_;
1040 invert_ = rhs.invert_;
1041 light_ = rhs.light_;
1042 tint_ = rhs.tint_;
1043
1044 colour_ = rhs.colour_;
1045
1046 composite_mode_ = rhs.composite_mode_;
1047 scroll_rate_x_ = rhs.scroll_rate_x_;
1048 scroll_rate_y_ = rhs.scroll_rate_y_;
1049 z_order_ = rhs.z_order_;
1050 z_layer_ = rhs.z_layer_;
1051 z_depth_ = rhs.z_depth_;
1052
1053 if (rhs.text_properties_)
1054 text_properties_.reset(new TextProperties(*rhs.text_properties_));
1055 if (rhs.drift_properties_)
1056 drift_properties_.reset(new DriftProperties(*rhs.drift_properties_));
1057 if (rhs.digit_properties_)
1058 digit_properties_.reset(new DigitProperties(*rhs.digit_properties_));
1059 if (rhs.button_properties_)
1060 button_properties_.reset(new ButtonProperties(*rhs.button_properties_));
1061
1062 wipe_copy_ = rhs.wipe_copy_;
1063 }
1064
1065 return *this;
1066 }
1067
MakeSureHaveTextProperties()1068 void GraphicsObject::Impl::MakeSureHaveTextProperties() {
1069 if (!text_properties_) {
1070 text_properties_.reset(new Impl::TextProperties());
1071 }
1072 }
1073
MakeSureHaveDriftProperties()1074 void GraphicsObject::Impl::MakeSureHaveDriftProperties() {
1075 if (!drift_properties_) {
1076 drift_properties_.reset(new Impl::DriftProperties());
1077 }
1078 }
1079
MakeSureHaveDigitProperties()1080 void GraphicsObject::Impl::MakeSureHaveDigitProperties() {
1081 if (!digit_properties_) {
1082 digit_properties_.reset(new Impl::DigitProperties());
1083 }
1084 }
1085
MakeSureHaveButtonProperties()1086 void GraphicsObject::Impl::MakeSureHaveButtonProperties() {
1087 if (!button_properties_) {
1088 button_properties_.reset(new Impl::ButtonProperties());
1089 }
1090 }
1091
1092 // boost::serialization support
1093 template <class Archive>
serialize(Archive & ar,unsigned int version)1094 void GraphicsObject::Impl::serialize(Archive& ar, unsigned int version) {
1095 ar& visible_& x_& y_& whatever_adjust_vert_operates_on_& origin_x_& origin_y_&
1096 rep_origin_x_& rep_origin_y_& width_& height_& rotation_& patt_no_&
1097 alpha_& clip_& mono_& invert_& tint_& colour_& composite_mode_&
1098 text_properties_& wipe_copy_;
1099
1100 if (version > 0) {
1101 ar& drift_properties_;
1102 }
1103
1104 if (version > 1) {
1105 ar& digit_properties_;
1106 }
1107
1108 if (version > 2) {
1109 ar& adjust_x_& adjust_y_& adjust_alpha_;
1110 }
1111
1112 if (version > 3) {
1113 ar& hq_width_& hq_height_& button_properties_;
1114 }
1115
1116 if (version > 4) {
1117 ar& own_clip_;
1118 }
1119
1120 if (version > 5) {
1121 ar& z_order_& z_layer_& z_depth_;
1122 }
1123
1124 if (version < 7) {
1125 // Before version 7, tint and colour were set incorrectly. Therefore the
1126 // vast majority of values in save games were set incorrectly. Oops. Set to
1127 // the default here.
1128 tint_ = RGBColour::Black();
1129 colour_ = RGBAColour::Clear();
1130 }
1131 }
1132
1133 // -----------------------------------------------------------------------
1134
1135 // Explicit instantiations for text archives (since we hide the
1136 // implementation)
1137
1138 template void GraphicsObject::Impl::serialize<boost::archive::text_oarchive>(
1139 boost::archive::text_oarchive& ar,
1140 unsigned int version);
1141
1142 template void GraphicsObject::Impl::serialize<boost::archive::text_iarchive>(
1143 boost::archive::text_iarchive& ar,
1144 unsigned int version);
1145
1146 // -----------------------------------------------------------------------
1147 // GraphicsObject::Impl::TextProperties
1148 // -----------------------------------------------------------------------
1149 template <class Archive>
serialize(Archive & ar,unsigned int version)1150 void GraphicsObject::Impl::TextProperties::serialize(Archive& ar,
1151 unsigned int version) {
1152 ar& value& text_size& xspace& yspace& char_count& colour& shadow_colour;
1153 }
1154
1155 // -----------------------------------------------------------------------
1156
1157 // Explicit instantiations for text archives (since we hide the
1158 // implementation)
1159
1160 template void GraphicsObject::Impl::TextProperties::serialize<
1161 boost::archive::text_oarchive>(boost::archive::text_oarchive& ar,
1162 unsigned int version);
1163
1164 template void GraphicsObject::Impl::TextProperties::serialize<
1165 boost::archive::text_iarchive>(boost::archive::text_iarchive& ar,
1166 unsigned int version);
1167
1168 // -----------------------------------------------------------------------
1169 // GraphicsObject::Impl::DirftProperties
1170 // -----------------------------------------------------------------------
1171 template <class Archive>
serialize(Archive & ar,unsigned int version)1172 void GraphicsObject::Impl::DriftProperties::serialize(Archive& ar,
1173 unsigned int version) {
1174 ar& count& use_animation& start_pattern& end_pattern& total_animation_time_ms&
1175 yspeed& period& amplitude& use_drift& unknown_drift_property& driftspeed&
1176 drift_area;
1177 }
1178
1179 // -----------------------------------------------------------------------
1180
1181 template void GraphicsObject::Impl::DriftProperties::serialize<
1182 boost::archive::text_oarchive>(boost::archive::text_oarchive& ar,
1183 unsigned int version);
1184
1185 template void GraphicsObject::Impl::DriftProperties::serialize<
1186 boost::archive::text_iarchive>(boost::archive::text_iarchive& ar,
1187 unsigned int version);
1188
1189 // -----------------------------------------------------------------------
1190 // GraphicsObject::Impl::DigitProperties
1191 // -----------------------------------------------------------------------
1192 template <class Archive>
serialize(Archive & ar,unsigned int version)1193 void GraphicsObject::Impl::DigitProperties::serialize(Archive& ar,
1194 unsigned int version) {
1195 ar& value& digits& zero& sign& pack& space;
1196 }
1197
1198 // -----------------------------------------------------------------------
1199
1200 template void GraphicsObject::Impl::DigitProperties::serialize<
1201 boost::archive::text_oarchive>(boost::archive::text_oarchive& ar,
1202 unsigned int version);
1203
1204 template void GraphicsObject::Impl::DigitProperties::serialize<
1205 boost::archive::text_iarchive>(boost::archive::text_iarchive& ar,
1206 unsigned int version);
1207
1208 // -----------------------------------------------------------------------
1209 // GraphicsObject::Impl::ButtonProperties
1210 // -----------------------------------------------------------------------
1211 template <class Archive>
serialize(Archive & ar,unsigned int version)1212 void GraphicsObject::Impl::ButtonProperties::serialize(Archive& ar,
1213 unsigned int version) {
1214 // The override values are stuck here because I'm not sure about
1215 // initialization otherwise.
1216 ar& is_button& action& se& group& button_number& state& using_overides&
1217 pattern_override& x_offset_override& y_offset_override;
1218 }
1219
1220 // -----------------------------------------------------------------------
1221
1222 template void GraphicsObject::Impl::ButtonProperties::serialize<
1223 boost::archive::text_oarchive>(boost::archive::text_oarchive& ar,
1224 unsigned int version);
1225
1226 template void GraphicsObject::Impl::ButtonProperties::serialize<
1227 boost::archive::text_iarchive>(boost::archive::text_iarchive& ar,
1228 unsigned int version);
1229