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 #ifndef SRC_SYSTEMS_BASE_GRAPHICS_OBJECT_H_
29 #define SRC_SYSTEMS_BASE_GRAPHICS_OBJECT_H_
30 
31 #include <boost/scoped_ptr.hpp>
32 #include <boost/shared_ptr.hpp>
33 #include <boost/serialization/access.hpp>
34 #include <boost/serialization/version.hpp>
35 
36 #include <string>
37 #include <vector>
38 
39 #include "systems/base/colour.h"
40 #include "systems/base/rect.h"
41 
42 class RLMachine;
43 class GraphicsObject;
44 class GraphicsObjectSlot;
45 class GraphicsObjectData;
46 class ObjectMutator;
47 
48 // Describes an independent, movable graphical object on the
49 // screen. GraphicsObject, internally, references a copy-on-write
50 // datastructure, which in turn has optional components to save
51 // memory.
52 //
53 // TODO(erg): I want to put index checks on a lot of these accessors.
54 class GraphicsObject {
55  public:
56   GraphicsObject();
57   GraphicsObject(const GraphicsObject& obj);
58   ~GraphicsObject();
59   GraphicsObject& operator=(const GraphicsObject& obj);
60 
61   // Object Position Accessors
62 
63   // This code, while a boolean, uses an int so that we can get rid
64   // of one template parameter in one of the generic operation
65   // functors.
visible()66   int visible() const { return impl_->visible_; }
67   void SetVisible(const int in);
68 
x()69   int x() const { return impl_->x_; }
70   void SetX(const int x);
71 
y()72   int y() const { return impl_->y_; }
73   void SetY(const int y);
74 
x_adjustment(int idx)75   int x_adjustment(int idx) const { return impl_->adjust_x_[idx]; }
76   int GetXAdjustmentSum() const;
77   void SetXAdjustment(int idx, int x);
78 
y_adjustment(int idx)79   int y_adjustment(int idx) const { return impl_->adjust_y_[idx]; }
80   int GetYAdjustmentSum() const;
81   void SetYAdjustment(int idx, int y);
82 
vert()83   int vert() const { return impl_->whatever_adjust_vert_operates_on_; }
84   void SetVert(const int vert);
85 
origin_x()86   int origin_x() const { return impl_->origin_x_; }
87   void SetOriginX(const int x);
88 
origin_y()89   int origin_y() const { return impl_->origin_y_; }
90   void SetOriginY(const int y);
91 
rep_origin_x()92   int rep_origin_x() const { return impl_->rep_origin_x_; }
93   void SetRepOriginX(const int x);
94 
rep_origin_y()95   int rep_origin_y() const { return impl_->rep_origin_y_; }
96   void SetRepOriginY(const int y);
97 
98   // Note: width/height are object scale percentages.
width()99   int width() const { return impl_->width_; }
100   void SetWidth(const int in);
height()101   int height() const { return impl_->height_; }
102   void SetHeight(const int in);
103 
104   // Note: width/height are object scale factors out of 1000.
hq_width()105   int hq_width() const { return impl_->hq_width_; }
106   void SetHqWidth(const int in);
hq_height()107   int hq_height() const { return impl_->hq_height_; }
108   void SetHqHeight(const int in);
109 
110   float GetWidthScaleFactor() const;
111   float GetHeightScaleFactor() const;
112 
rotation()113   int rotation() const { return impl_->rotation_; }
114   void SetRotation(const int in);
115 
116   int PixelWidth() const;
117   int PixelHeight() const;
118 
119   // Object attribute accessors
120   int GetPattNo() const;
121   void SetPattNo(const int in);
122 
mono()123   int mono() const { return impl_->mono_; }
124   void SetMono(const int in);
125 
invert()126   int invert() const { return impl_->invert_; }
127   void SetInvert(const int in);
128 
light()129   int light() const { return impl_->light_; }
130   void SetLight(const int in);
131 
tint()132   const RGBColour& tint() const { return impl_->tint_; }
tint_red()133   int tint_red() const { return impl_->tint_.r(); }
tint_green()134   int tint_green() const { return impl_->tint_.g(); }
tint_blue()135   int tint_blue() const { return impl_->tint_.b(); }
136   void SetTint(const RGBColour& colour);
137   void SetTintRed(const int in);
138   void SetTintGreen(const int in);
139   void SetTintBlue(const int in);
140 
colour()141   const RGBAColour& colour() const { return impl_->colour_; }
colour_red()142   int colour_red() const { return impl_->colour_.r(); }
colour_green()143   int colour_green() const { return impl_->colour_.g(); }
colour_blue()144   int colour_blue() const { return impl_->colour_.b(); }
colour_level()145   int colour_level() const { return impl_->colour_.a(); }
146   void SetColour(const RGBAColour& colour);
147   void SetColourRed(const int in);
148   void SetColourGreen(const int in);
149   void SetColourBlue(const int in);
150   void SetColourLevel(const int in);
151 
composite_mode()152   int composite_mode() const { return impl_->composite_mode_; }
153   void SetCompositeMode(const int in);
154 
scroll_rate_x()155   int scroll_rate_x() const { return impl_->scroll_rate_x_; }
156   void SetScrollRateX(const int x);
157 
scroll_rate_y()158   int scroll_rate_y() const { return impl_->scroll_rate_y_; }
159   void SetScrollRateY(const int y);
160 
161   // Three level zorder.
z_order()162   int z_order() const { return impl_->z_order_; }
163   void SetZOrder(const int in);
z_layer()164   int z_layer() const { return impl_->z_layer_; }
165   void SetZLayer(const int in);
z_depth()166   int z_depth() const { return impl_->z_depth_; }
167   void SetZDepth(const int in);
168 
169   int GetComputedAlpha() const;
raw_alpha()170   int raw_alpha() const { return impl_->alpha_; }
171   void SetAlpha(const int alpha);
172 
alpha_adjustment(int idx)173   int alpha_adjustment(int idx) const { return impl_->adjust_alpha_[idx]; }
174   void SetAlphaAdjustment(int idx, int alpha);
175 
clip_rect()176   const Rect& clip_rect() const { return impl_->clip_; }
has_clip_rect()177   bool has_clip_rect() const {
178     return impl_->clip_.width() >= 0 || impl_->clip_.height() >= 0;
179   }
180   void ClearClipRect();
181   void SetClipRect(const Rect& rec);
182 
own_clip_rect()183   const Rect& own_clip_rect() const { return impl_->own_clip_; }
has_own_clip_rect()184   bool has_own_clip_rect() const {
185     return impl_->own_clip_.width() >= 0 || impl_->own_clip_.height() >= 0;
186   }
187   void ClearOwnClipRect();
188   void SetOwnClipRect(const Rect& rec);
189 
has_object_data()190   bool has_object_data() const { return object_data_.get(); }
191 
192   GraphicsObjectData& GetObjectData();
193   void SetObjectData(GraphicsObjectData* obj);
194 
195   // Render!
196   void Render(int objNum, const GraphicsObject* parent, std::ostream* tree);
197 
198   // Frees the object data. Corresponds to objFree, but is also invoked by
199   // other commands.
200   void FreeObjectData();
201 
202   // Resets/reinitializes all the object parameters without deleting the loaded
203   // graphics object data.
204   void InitializeParams();
205 
206   // Both frees the object data and initializes parameters.
207   void FreeDataAndInitializeParams();
208 
wipe_copy()209   int wipe_copy() const { return impl_->wipe_copy_; }
210   void SetWipeCopy(const int wipe_copy);
211 
212   // Called each pass through the gameloop to see if this object needs
213   // to force a redraw, or something.
214   void Execute(RLMachine& machine);
215 
216   // Text Object accessors
217   void SetTextText(const std::string& utf8str);
218   const std::string& GetTextText() const;
219 
220   void SetTextOps(int size,
221                   int xspace,
222                   int yspace,
223                   int char_count,
224                   int colour,
225                   int shadow);
226   int GetTextSize() const;
227   int GetTextXSpace() const;
228   int GetTextYSpace() const;
229   int GetTextCharCount() const;
230   int GetTextColour() const;
231   int GetTextShadowColour() const;
232 
233   // Drift object accessors
234   void SetDriftOpts(int count,
235                     int use_animation,
236                     int start_pattern,
237                     int end_pattern,
238                     int total_animation_time_ms,
239                     int yspeed,
240                     int period,
241                     int amplitude,
242                     int use_drift,
243                     int unknown_drift_property,
244                     int driftspeed,
245                     Rect driftarea);
246 
247   int GetDriftParticleCount() const;
248   int GetDriftUseAnimation() const;
249   int GetDriftStartPattern() const;
250   int GetDriftEndPattern() const;
251   int GetDriftAnimationTime() const;
252   int GetDriftYSpeed() const;
253   int GetDriftPeriod() const;
254   int GetDriftAmplitude() const;
255   int GetDriftUseDrift() const;
256   int GetDriftUnknown() const;
257   int GetDriftDriftSpeed() const;
258   Rect GetDriftArea() const;
259 
260   // Digit object accessors
261   void SetDigitValue(int value);
262   void SetDigitOpts(int digits, int zero, int sign, int pack, int space);
263 
264   int GetDigitValue() const;
265   int GetDigitDigits() const;
266   int GetDigitZero() const;
267   int GetDigitSign() const;
268   int GetDigitPack() const;
269   int GetDigitSpace() const;
270 
271   // Button object accessors
272   void SetButtonOpts(int action, int se, int group, int button_number);
273   void SetButtonState(int state);
274 
275   int IsButton() const;
276   int GetButtonAction() const;
277   int GetButtonSe() const;
278   int GetButtonGroup() const;
279   int GetButtonNumber() const;
280   int GetButtonState() const;
281 
282   // Called only from ButtonObjectSelectLongOperation. Sets override
283   // properties.
284   void SetButtonOverrides(int override_pattern,
285                           int override_x_offset,
286                           int override_y_offset);
287   void ClearButtonOverrides();
288 
289   bool GetButtonUsingOverides() const;
290   int GetButtonPatternOverride() const;
291   int GetButtonXOffsetOverride() const;
292   int GetButtonYOffsetOverride() const;
293 
294   // Adds a mutator to the list of active mutators. GraphicsSystem takes
295   // ownership of the passed in object.
296   void AddObjectMutator(std::unique_ptr<ObjectMutator> mutator);
297 
298   // Returns true if a mutator matching the following parameters is currently
299   // running.
300   bool IsMutatorRunningMatching(int repno, const std::string& name);
301 
302   // Ends all mutators that match the given parameters.
303   void EndObjectMutatorMatching(RLMachine& machine,
304                                 int repno,
305                                 const std::string& name,
306                                 int speedup);
307 
308   // Returns a string for each mutator.
309   std::vector<std::string> GetMutatorNames() const;
310 
311   // Returns the number of GraphicsObject instances sharing the
312   // internal copy-on-write object. Only used in unit testing.
reference_count()313   int32_t reference_count() const { return impl_.use_count(); }
314 
315   // Whether we have the default shared data. Only used in unit testing.
is_cleared()316   bool is_cleared() const { return impl_ == s_empty_impl; }
317 
318  private:
319   // Makes the internal copy for our copy-on-write semantics. This function
320   // checks to see if our Impl object has only one reference to it. If it
321   // doesn't, a local copy is made.
322   void MakeImplUnique();
323 
324   // Immediately delete all mutators; doesn't run their SetToEnd() method.
325   void DeleteObjectMutators();
326 
327   // Implementation data structure. GraphicsObject::Impl is the internal data
328   // store for GraphicsObjects' copy-on-write semantics.
329   struct Impl {
330     Impl();
331     Impl(const Impl& rhs);
332     ~Impl();
333 
334     Impl& operator=(const Impl& rhs);
335 
336     // Visibility. Different from whether an object is in the bg or fg layer
337     bool visible_;
338 
339     // The positional coordinates of the object
340     int x_, y_;
341 
342     // Eight additional parameters that are added to x and y during
343     // rendering.
344     int adjust_x_[8], adjust_y_[8];
345 
346     // Whatever obj_adjust_vert operates on; what's this used for?
347     int whatever_adjust_vert_operates_on_;
348 
349     // The origin
350     int origin_x_, origin_y_;
351 
352     // "Rep" origin. This second origin is added to the normal origin
353     // only in cases of rotating and scaling.
354     int rep_origin_x_, rep_origin_y_;
355 
356     // The size of the object, given in integer percentages of [0,
357     // 100]. Used for scaling.
358     int width_, height_;
359 
360     // A second scaling factor, given between [0, 1000].
361     int hq_width_, hq_height_;
362 
363     // The rotation degree / 10
364     int rotation_;
365 
366     // Object attributes.
367 
368     // The region ("pattern") in g00 bitmaps
369     int patt_no_;
370 
371     // The source alpha for this image
372     int alpha_;
373 
374     // Eight additional alphas that are averaged during rendering.
375     int adjust_alpha_[8];
376 
377     // The clipping region for this image
378     Rect clip_;
379 
380     // A second clipping region in the object's own space.
381     Rect own_clip_;
382 
383     // The monochrome transformation
384     int mono_;
385 
386     // The invert transformation
387     int invert_;
388 
389     int light_;
390 
391     RGBColour tint_;
392 
393     // Applies a colour to the object by blending it directly at the
394     // alpha components opacity.
395     RGBAColour colour_;
396 
397     int composite_mode_;
398 
399     int scroll_rate_x_, scroll_rate_y_;
400 
401     // Three deep zordering.
402     int z_order_, z_layer_, z_depth_;
403 
404     // Text Object properties
405     struct TextProperties {
406       TextProperties();
407 
408       std::string value;
409 
410       int text_size, xspace, yspace;
411 
412       int char_count;
413       int colour;
414       int shadow_colour;
415 
416       // boost::serialization support
417       template <class Archive>
418       void serialize(Archive& ar, unsigned int version);
419     };
420 
421     void MakeSureHaveTextProperties();
422     boost::scoped_ptr<TextProperties> text_properties_;
423 
424     // Drift Object properties
425     struct DriftProperties {
426       DriftProperties();
427 
428       int count;
429 
430       int use_animation;
431       int start_pattern;
432       int end_pattern;
433       int total_animation_time_ms;
434 
435       int yspeed;
436 
437       int period;
438       int amplitude;
439 
440       int use_drift;
441       int unknown_drift_property;
442       int driftspeed;
443 
444       Rect drift_area;
445 
446       // boost::serialization support
447       template <class Archive>
448       void serialize(Archive& ar, unsigned int version);
449     };
450 
451     void MakeSureHaveDriftProperties();
452     boost::scoped_ptr<DriftProperties> drift_properties_;
453 
454     // Digit Object properties
455     struct DigitProperties {
456       DigitProperties();
457 
458       int value;
459 
460       int digits;
461       int zero;
462       int sign;
463       int pack;
464       int space;
465 
466       // boost::serialization support
467       template <class Archive>
468       void serialize(Archive& ar, unsigned int version);
469     };
470 
471     void MakeSureHaveDigitProperties();
472     boost::scoped_ptr<DigitProperties> digit_properties_;
473 
474     // Button Object properties
475     struct ButtonProperties {
476       ButtonProperties();
477 
478       int is_button;
479 
480       int action;
481       int se;
482       int group;
483       int button_number;
484 
485       int state;
486 
487       bool using_overides;
488       int pattern_override;
489       int x_offset_override;
490       int y_offset_override;
491 
492       // boost::serialization support
493       template <class Archive>
494       void serialize(Archive& ar, unsigned int version);
495     };
496 
497     void MakeSureHaveButtonProperties();
498     boost::scoped_ptr<ButtonProperties> button_properties_;
499 
500     // The wipe_copy bit
501     int wipe_copy_;
502 
503     friend class boost::serialization::access;
504 
505     // boost::serialization support
506     template <class Archive>
507     void serialize(Archive& ar, unsigned int version);
508   };
509 
510   // Default empty GraphicsObject::Impl. This variable is allocated
511   // once, and then is used as the initial value of impl_, where it
512   // is cloned on write.
513   static const boost::shared_ptr<GraphicsObject::Impl> s_empty_impl;
514 
515   // Our actual implementation data
516   boost::shared_ptr<GraphicsObject::Impl> impl_;
517 
518   // The actual data used to render the object
519   boost::scoped_ptr<GraphicsObjectData> object_data_;
520 
521   // Tasks that run every tick. Used to mutate object parameters over time (and
522   // how we check from a blocking LongOperation if the mutation is ongoing).
523   //
524   // I think R23 mentioned that these were called "Parameter Events" in the
525   // RLMAX SDK.
526   std::vector<std::unique_ptr<ObjectMutator>> object_mutators_;
527 
528   friend class boost::serialization::access;
529 
530   // boost::serialization support
531   template <class Archive>
532   void serialize(Archive& ar, unsigned int version);
533 };
534 
535 BOOST_CLASS_VERSION(GraphicsObject::Impl, 7)
536 
537 static const int OBJ_FG = 0;
538 static const int OBJ_BG = 1;
539 
540 #endif  // SRC_SYSTEMS_BASE_GRAPHICS_OBJECT_H_
541