1 /*--License:
2 	Kyra Sprite Engine
3 	Copyright Lee Thomason (Grinning Lizard Software) 2001-2005
4 	www.grinninglizard.com/kyra
5 	www.sourceforge.net/projects/kyra
6 
7 	Kyra is provided under the LGPL.
8 
9 	I kindly request you display a splash screen (provided in the HTML documentation)
10 	to promote Kyra and acknowledge the software and everyone who has contributed to it,
11 	but it is not required by the license.
12 
13 --- LGPL License --
14 
15     This library is free software; you can redistribute it and/or
16     modify it under the terms of the GNU Lesser General Public
17     License as published by the Free Software Foundation; either
18     version 2.1 of the License, or (at your option) any later version.
19 
20     This library is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23     Lesser General Public License for more details.
24 
25     You should have received a copy of the GNU Lesser General Public
26     License along with this library; if not, write to the Free Software
27     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 
29 	The full text of the license can be found in lgpl.txt
30 */
31 
32 #include "image.h"
33 #include "SDL.h"
34 #include "engine.h"
35 #include "../../grinliz/glgeometry.h"
36 
37 using namespace grinliz;
38 
39 
KrImage()40 KrImage::KrImage()
41 {
42 	for( int i=0; i<KR_MAX_WINDOWS; ++i )
43 	{
44 		wasVisibleAtLastFlush[i] = true;
45 //		haveCacheRect[i] = false;
46 	}
47 }
48 
49 
AddedtoTree()50 void KrImage::AddedtoTree()
51 {
52 	KrImNode::AddedtoTree();
53 	GLASSERT( bounds[0].IsValid() );
54 }
55 
56 
LeavingTree()57 void KrImage::LeavingTree()
58 {
59 	GLASSERT( Engine() );
60 	for( int i=0; i<Engine()->NumWindows(); ++i )
61 	{
62 		if ( wasVisibleAtLastFlush[i] )
63 		{
64 			Engine()->DirtyRectangle(i)->AddRectangle( bounds[i] );
65 		}
66 	}
67 	KrImNode::LeavingTree();
68 }
69 
70 
FlushInvalid(int window,bool cache)71 void KrImage::FlushInvalid( int window, bool cache )
72 {
73 	// This whole cache mess takes advantage that the 2 rectangles generated
74 	// by a particular sprite will almost certainly overlap and can be treated
75 	// as one. Cache the first. When the 2nd comes in, if they intersect, union
76 	// together and add both. Else add seperately. Doesn't make much of a
77 	// difference, pulling for now.
78 	//
79 //	if ( cache )
80 //	{
81 //		// Make sure our bounds get re-painted.
82 //		if ( wasVisibleAtLastFlush[window] || IsVisible(window) )
83 //		{
84 //			GLASSERT( haveCacheRect[window] == false );
85 //			haveCacheRect[window] = true;
86 //			cacheRect[window] = bounds[window];
87 //		}
88 //	}
89 //	else
90 //	{
91 //		if ( haveCacheRect[window] )
92 //		{
93 //			// Make sure our bounds get re-painted.
94 //			if ( wasVisibleAtLastFlush[window] || IsVisible(window) )
95 //			{
96 //				if ( cacheRect[window].Intersect( bounds[window] ) )
97 //				{
98 //					cacheRect[window].DoUnion( bounds[window] );
99 //					Engine()->DirtyRectangle(window)->AddRectangle( cacheRect[window] );
100 //				}
101 //				else
102 //				{
103 //					Engine()->DirtyRectangle(window)->AddRectangle( cacheRect[window] );
104 //					Engine()->DirtyRectangle(window)->AddRectangle( bounds[window] );
105 //				}
106 //			}
107 //			haveCacheRect[window] = false;
108 //		}
109 //		else
110 //		{
111 			// The entirety of "the old code."
112 			// Make sure our bounds get re-painted.
113 			//GLASSERT( bounds[window].IsValid() );
114 			bool vis = IsVisible(window);
115 			GLASSERT( !vis || bounds[window].IsValid() );
116 
117 			if ( wasVisibleAtLastFlush[window] || vis )
118 			{
119 				Engine()->DirtyRectangle(window)->AddRectangle( bounds[window] );
120 				wasVisibleAtLastFlush[window] = vis;
121 			}
122 //		}
123 //	}
124 }
125 
126 
CheckCollision(KrImage * other,int window)127 bool KrImage::CheckCollision( KrImage* other, int window )
128 {
129 	// Only sprites and canvases collide.
130 	if (    !( other->ToSprite() || other->ToCanvas() )
131 		 || !( this->ToSprite() || this->ToCanvas()   ) )
132 	{
133 		return false;
134 	}
135 
136 	// If the bounding boxes don't overlap, they don't collide.
137 	if ( !this->Bounds( window ).Intersect( other->Bounds( window ) ) )
138 	{
139 		return false;
140 	}
141 
142 	// Visiibily
143 	if ( !this->IsVisible( window ) || !other->IsVisible( window ) )
144 	{
145 		return false;
146 	}
147 
148 	// Transparency
149 	if (    this->CompositeCForm( window ).Alpha() == 0
150 		 || other->CompositeCForm( window ).Alpha() == 0 )
151 	{
152 		return false;
153 	}
154 
155 //	GLOUTPUT( "BoundingBoxPass: %s [%d,%d]-[%d,%d]\n",
156 //			  other->NodeName().c_str(),
157 //			  other->Bounds( 0 ).xmin,
158 //			  other->Bounds( 0 ).ymin,
159 //			  other->Bounds( 0 ).xmax,
160 //			  other->Bounds( 0 ).ymax );
161 
162 
163 	// Not colliding with text is a good idea -- but I fear I'll be chasing
164 	// special cases and widget behavior forever. So removing check.
165 
166 	//	// Don't collide with text.
167 	//	if (	other->Parent()
168 	//		 && other->Parent()->Parent()
169 	//		 && other->Parent()->Parent()->ToTextBox() )
170 	//	{
171 	//		return false;
172 	//	}
173 	//	if (	this->Parent()
174 	//		 &&	this->Parent()->Parent()
175 	//		 &&	this->Parent()->Parent()->ToTextBox() )
176 	//	{
177 	//		return false;
178 	//	}
179 
180 	// The entire collision thing is base on a left-right model. Very important
181 	// to get that correct.
182 	KrImage* left  = 0;
183 	KrImage* right = 0;
184 
185 	if ( other->Bounds( window ).min.x > this->Bounds( window ).min.x )
186 	{
187 		right = other;
188 		left  = this;
189 	}
190 	else
191 	{
192 		right = this;
193 		left = other;
194 	}
195 
196 	KrCollisionMap *leftMap, *rightMap;
197 
198 	leftMap  = left->Resource()->GetCollisionMap( left, window );
199 	rightMap = right->Resource()->GetCollisionMap( right, window );
200 
201 	Rectangle2I isect = left->Bounds( window );
202 	isect.DoIntersection( right->Bounds( window ) );
203 
204 	if ( leftMap && rightMap )
205 	{
206 		// Okay, we might actually collide after all that.
207 		return leftMap->Collide( right->Bounds( window ).min.x - left->Bounds( window ).min.x,
208 								 right->Bounds( window ).min.y - left->Bounds( window ).min.y,
209 								 isect,
210 								 rightMap );
211 
212 	}
213 	return false;
214 }
215 
216 
217