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 "effects/wipe_effect.h"
29 
30 #include <cmath>
31 
32 #include "machine/rlmachine.h"
33 #include "systems/base/graphics_system.h"
34 #include "systems/base/surface.h"
35 #include "systems/base/system.h"
36 
37 // -----------------------------------------------------------------------
38 // WipeEffect base class
39 // -----------------------------------------------------------------------
40 
WipeEffect(RLMachine & machine,std::shared_ptr<Surface> src,std::shared_ptr<Surface> dst,const Size & screen_size,int time,int interpolation)41 WipeEffect::WipeEffect(RLMachine& machine,
42                        std::shared_ptr<Surface> src,
43                        std::shared_ptr<Surface> dst,
44                        const Size& screen_size,
45                        int time,
46                        int interpolation)
47     : Effect(machine, src, dst, screen_size, time),
48       interpolation_(interpolation),
49       interpolation_in_pixels_(0) {
50   if (interpolation_)
51     interpolation_in_pixels_ = int(pow(float(2), interpolation) * 2.5);
52 }
53 
~WipeEffect()54 WipeEffect::~WipeEffect() {}
55 
56 // Calculates the size of the interpolation and main polygons.
57 //
58 // There are 3 possible stages:
59 // - [0, interpolation_in_pixels_) - Draw only the
60 //   transition. (sizeOfMainPolygon == 0, sizeOfInterpolation ==
61 //   amountVisible)
62 // - [interpolation_in_pixels_, sizeOfScreen) - Draw both
63 //   polygons. (sizeOfMainPolygon == amountVisible -
64 //   interpolation_in_pixels_, sizeOfInterpolation == amountVisible)
65 // - [height, height + interpolation_in_pixels_) - Draw both
66 //   polygons, flooring the height of the transition to
CalculateSizes(int currentTime,int & sizeOfInterpolation,int & sizeOfMainPolygon,int sizeOfScreen)67 void WipeEffect::CalculateSizes(int currentTime,
68                                 int& sizeOfInterpolation,
69                                 int& sizeOfMainPolygon,
70                                 int sizeOfScreen) {
71   int amountVisible = int((float(currentTime) / duration()) *
72                           (sizeOfScreen + interpolation_in_pixels_));
73   if (amountVisible < interpolation_in_pixels_) {
74     sizeOfInterpolation = amountVisible;
75     sizeOfMainPolygon = 0;
76   } else if (amountVisible < sizeOfScreen) {
77     sizeOfInterpolation = interpolation_in_pixels_;
78     sizeOfMainPolygon = amountVisible - interpolation_in_pixels_;
79   } else if (amountVisible < sizeOfScreen + interpolation_in_pixels_) {
80     sizeOfMainPolygon = amountVisible - interpolation_in_pixels_;
81     sizeOfInterpolation = sizeOfScreen - sizeOfMainPolygon;
82   }
83 }
84 
BlitOriginalImage() const85 bool WipeEffect::BlitOriginalImage() const { return true; }
86 
87 // -----------------------------------------------------------------------
88 // WipeTopToBottomEffect
89 // -----------------------------------------------------------------------
90 
WipeTopToBottomEffect(RLMachine & machine,std::shared_ptr<Surface> src,std::shared_ptr<Surface> dst,const Size & screen_size,int time,int interpolation)91 WipeTopToBottomEffect::WipeTopToBottomEffect(RLMachine& machine,
92                                              std::shared_ptr<Surface> src,
93                                              std::shared_ptr<Surface> dst,
94                                              const Size& screen_size,
95                                              int time,
96                                              int interpolation)
97     : WipeEffect(machine, src, dst, screen_size, time, interpolation) {}
98 
~WipeTopToBottomEffect()99 WipeTopToBottomEffect::~WipeTopToBottomEffect() {}
100 
PerformEffectForTime(RLMachine & machine,int currentTime)101 void WipeTopToBottomEffect::PerformEffectForTime(RLMachine& machine,
102                                                  int currentTime) {
103   int sizeOfInterpolation, sizeOfMainPolygon;
104   CalculateSizes(currentTime, sizeOfInterpolation, sizeOfMainPolygon, height());
105 
106   if (sizeOfMainPolygon) {
107     src_surface().RenderToScreen(Rect::REC(0, 0, width(), sizeOfMainPolygon),
108                                  Rect::REC(0, 0, width(), sizeOfMainPolygon),
109                                  255);
110   }
111 
112   if (sizeOfInterpolation) {
113     int opacity[4] = {255, 255, 0, 0};
114 
115     src_surface().RenderToScreen(
116         Rect::GRP(0,
117                   sizeOfMainPolygon,
118                   width(),
119                   sizeOfMainPolygon + sizeOfInterpolation),
120         Rect::GRP(0,
121                   sizeOfMainPolygon,
122                   width(),
123                   sizeOfMainPolygon + sizeOfInterpolation),
124         opacity);
125   }
126 }
127 
128 // -----------------------------------------------------------------------
129 // WipeBottomToTopEffect
130 // -----------------------------------------------------------------------
131 
WipeBottomToTopEffect(RLMachine & machine,std::shared_ptr<Surface> src,std::shared_ptr<Surface> dst,const Size & screen_size,int time,int interpolation)132 WipeBottomToTopEffect::WipeBottomToTopEffect(RLMachine& machine,
133                                              std::shared_ptr<Surface> src,
134                                              std::shared_ptr<Surface> dst,
135                                              const Size& screen_size,
136                                              int time,
137                                              int interpolation)
138     : WipeEffect(machine, src, dst, screen_size, time, interpolation) {}
139 
~WipeBottomToTopEffect()140 WipeBottomToTopEffect::~WipeBottomToTopEffect() {}
141 
PerformEffectForTime(RLMachine & machine,int currentTime)142 void WipeBottomToTopEffect::PerformEffectForTime(RLMachine& machine,
143                                                  int currentTime) {
144   int sizeOfInterpolation, sizeOfMainPolygon;
145   CalculateSizes(currentTime, sizeOfInterpolation, sizeOfMainPolygon, height());
146 
147   // Render the sliding on frame
148   if (sizeOfMainPolygon) {
149     src_surface().RenderToScreen(
150         Rect::GRP(0, height() - sizeOfMainPolygon, width(), height()),
151         Rect::GRP(0, height() - sizeOfMainPolygon, width(), height()),
152         255);
153   }
154 
155   if (sizeOfInterpolation) {
156     int opacity[4] = {0, 0, 255, 255};
157     src_surface().RenderToScreen(
158         Rect::GRP(0,
159                   height() - sizeOfMainPolygon - sizeOfInterpolation,
160                   width(),
161                   height() - sizeOfMainPolygon),
162         Rect::GRP(0,
163                   height() - sizeOfMainPolygon - sizeOfInterpolation,
164                   width(),
165                   height() - sizeOfMainPolygon),
166         opacity);
167   }
168 }
169 
170 // -----------------------------------------------------------------------
171 // WipeFromLeftToRightEffect
172 // -----------------------------------------------------------------------
173 
WipeLeftToRightEffect(RLMachine & machine,std::shared_ptr<Surface> src,std::shared_ptr<Surface> dst,const Size & screen_size,int time,int interpolation)174 WipeLeftToRightEffect::WipeLeftToRightEffect(RLMachine& machine,
175                                              std::shared_ptr<Surface> src,
176                                              std::shared_ptr<Surface> dst,
177                                              const Size& screen_size,
178                                              int time,
179                                              int interpolation)
180     : WipeEffect(machine, src, dst, screen_size, time, interpolation) {}
181 
~WipeLeftToRightEffect()182 WipeLeftToRightEffect::~WipeLeftToRightEffect() {}
183 
PerformEffectForTime(RLMachine & machine,int currentTime)184 void WipeLeftToRightEffect::PerformEffectForTime(RLMachine& machine,
185                                                  int currentTime) {
186   int sizeOfInterpolation, sizeOfMainPolygon;
187   CalculateSizes(currentTime, sizeOfInterpolation, sizeOfMainPolygon, width());
188 
189   // CONTINUE FIXING THE WIPES HERE!
190 
191   if (sizeOfMainPolygon) {
192     src_surface().RenderToScreen(Rect::GRP(0, 0, sizeOfMainPolygon, height()),
193                                  Rect::GRP(0, 0, sizeOfMainPolygon, height()),
194                                  255);
195   }
196 
197   if (sizeOfInterpolation) {
198     int opacity[4] = {255, 0, 0, 255};
199     src_surface().RenderToScreen(
200         Rect::GRP(sizeOfMainPolygon,
201                   0,
202                   sizeOfMainPolygon + sizeOfInterpolation,
203                   height()),
204         Rect::GRP(sizeOfMainPolygon,
205                   0,
206                   sizeOfMainPolygon + sizeOfInterpolation,
207                   height()),
208         opacity);
209   }
210 }
211 
212 // -----------------------------------------------------------------------
213 // WipeFromRightToLeftEffect
214 // -----------------------------------------------------------------------
215 
WipeRightToLeftEffect(RLMachine & machine,std::shared_ptr<Surface> src,std::shared_ptr<Surface> dst,const Size & screen_size,int time,int interpolation)216 WipeRightToLeftEffect::WipeRightToLeftEffect(RLMachine& machine,
217                                              std::shared_ptr<Surface> src,
218                                              std::shared_ptr<Surface> dst,
219                                              const Size& screen_size,
220                                              int time,
221                                              int interpolation)
222     : WipeEffect(machine, src, dst, screen_size, time, interpolation) {}
223 
~WipeRightToLeftEffect()224 WipeRightToLeftEffect::~WipeRightToLeftEffect() {}
225 
PerformEffectForTime(RLMachine & machine,int currentTime)226 void WipeRightToLeftEffect::PerformEffectForTime(RLMachine& machine,
227                                                  int currentTime) {
228   int sizeOfInterpolation, sizeOfMainPolygon;
229   CalculateSizes(currentTime, sizeOfInterpolation, sizeOfMainPolygon, width());
230 
231   if (sizeOfMainPolygon) {
232     src_surface().RenderToScreen(
233         Rect::GRP(width() - sizeOfMainPolygon, 0, width(), height()),
234         Rect::GRP(width() - sizeOfMainPolygon, 0, width(), height()),
235         255);
236   }
237 
238   if (sizeOfInterpolation) {
239     int opacity[4] = {0, 255, 255, 0};
240     src_surface().RenderToScreen(
241         Rect::GRP(width() - sizeOfInterpolation - sizeOfMainPolygon,
242                   0,
243                   width() - sizeOfMainPolygon,
244                   height()),
245         Rect::GRP(width() - sizeOfInterpolation - sizeOfMainPolygon,
246                   0,
247                   width() - sizeOfMainPolygon,
248                   height()),
249         opacity);
250   }
251 }
252