View Javadoc

1   /*
2    * All Rights Reserved.
3    * Copyright (C) 1999-2005 Tsukuba Bunko.
4    *
5    * Licensed under the BSD License ("the License"); you may not use
6    * this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *       http://www.tsukuba-bunko.org/licenses/LICENSE.txt
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   * $Id: StageCanvas.java,v 1.3 2005/07/23 18:53:48 ppoi Exp $
18   */
19  package tsukuba_bunko.peko.canvas.stage;
20  
21  import	java.awt.Dimension;
22  import	java.awt.Graphics;
23  import	java.awt.Graphics2D;
24  import	java.awt.Image;
25  
26  import	java.awt.image.BufferedImage;
27  
28  import	java.util.Iterator;
29  import	java.util.Map;
30  
31  import	javax.swing.JComponent;
32  
33  import	tsukuba_bunko.peko.Logger;
34  
35  import	tsukuba_bunko.peko.resource.ResourceManager;
36  
37  
38  /***
39   * 舞台(ステージ)を描画するキャンバスです。
40   * @author	$Author: ppoi $
41   * @version	$Revision: 1.3 $
42   */
43  public class StageCanvas	extends JComponent	{
44  
45  	/***
46  	 * serial version UID
47  	 */
48  	private static final long	serialVersionUID	= -4344927132903559315L;
49  
50  	/***
51  	 * ステージ
52  	 */
53  	private Stage	_stage = null;
54  
55  	/***
56  	 * エフェクトを使用するかどうか
57  	 */
58  	private boolean	_usingEffect = false;
59  
60  	/***
61  	 * エフェクトマップ
62  	 */
63  	private Map	_effects = null;
64  
65  	/***
66  	 * 描画用オフスクリーンバッファ
67  	 */
68  	private BufferedImage	_screen = null;
69  
70  	/***
71  	 * 作業用オフスクリーンバッファ
72  	 */
73  	private BufferedImage	_working = null;
74  
75  	/***
76  	 * size cache
77  	 */
78  	private Dimension	_size = new Dimension();
79  
80  
81  	/***
82  	 * <code>StageCanvas</code> のインスタンスを作成します。
83  	 */
84  	public StageCanvas()
85  	{
86  		super();
87  		initialize();
88  	}
89  
90  
91  	/***
92  	 * このキャンバスで描画するステージを設定します。
93  	 * @param	stage	ステージ
94  	 */
95  	public void setStage( Stage stage )
96  	{
97  		if( _stage != null )	{
98  			_stage.dispose();
99  		}
100 
101 		_stage = stage;
102 		_stage.setStageCanvas( this );
103 	}
104 
105 	/***
106 	 * このキャンバスが現在描画しているステージを取得します。
107 	 * @return	ステージ
108 	 */
109 	public Stage getStage()
110 	{
111 		return _stage;
112 	}
113 
114 	/***
115 	 * エフェクトを使用するかどうかを設定します。
116 	 * @param	useEffect	エフェクトを使用する場合 <code>true</code>、それ以外の場合 <code>false</code>
117 	 */
118 	public void setUsingEffect( boolean useEffect )
119 	{
120 		_usingEffect = useEffect;
121 	}
122 
123 	/***
124 	 * エフェクトを使用するかどうかを取得します。
125 	 * @return	エフェクトを使用する場合 <code>true</code>、それ以外の場合 <code>false</code>
126 	 */
127 	public boolean isUsingEffect()
128 	{
129 		return _usingEffect;
130 	}
131 
132 	/***
133 	 * ステージキャンバスを初期化します。
134 	 */
135 	private void initialize()
136 	{
137 		ResourceManager	resources = ResourceManager.getInstance();
138 		Dimension	canvasSize = (Dimension)resources.getResource( "peko.canvas.canvas-size" );
139 
140 		super.setPreferredSize( canvasSize );
141 		super.setSize( canvasSize );
142 		_screen = new BufferedImage( canvasSize.width, canvasSize.height, BufferedImage.TYPE_INT_RGB );
143 		_working = new BufferedImage( canvasSize.width, canvasSize.height, BufferedImage.TYPE_INT_RGB );
144 
145 		super.setLayout( null );
146 		setDoubleBuffered( false );
147 
148 		_effects = new java.util.HashMap( 89 );
149 
150 		Effect	effect = new tsukuba_bunko.peko.canvas.stage.effect.MofingEffect();
151 		_effects.put( effect.getName(), effect );
152 
153 		effect = new tsukuba_bunko.peko.canvas.stage.effect.PataPataEffect();
154 		_effects.put( effect.getName(), effect );
155 
156 		effect = (Effect)_effects.get( "immediate" );
157 		if( effect == null )	{
158 			effect = new tsukuba_bunko.peko.canvas.stage.effect.ImmediateEffect();
159 			_effects.put( "immediate", effect );
160 		}
161 		_effects.put( null, effect );
162 	}
163 
164 
165 	/***
166 	 * キャンバスの描画内容を更新します。
167 	 */
168 	public void updateCanvas()
169 	{
170 		updateCanvas( null );
171 	}
172 
173 	/***
174 	 * 指定されたエフェクトを用いて、キャンバスの描画内容を更新します。
175 	 * @param	effectName	更新時に使用するエフェクト名
176 	 */
177 	public void updateCanvas( String effectName )
178 	{
179 		if( !isEnabled() )	{
180 			return;
181 		}
182 
183 		Graphics2D	g2 = _working.createGraphics();
184 		Dimension	size = getSize( _size );
185 
186 		if( _stage.getSlide() == null )	{
187 			Image	image = _stage.getBackgroundImage();
188 			if( image != null )	{
189 				g2.drawImage( image, 0, 0, this );
190 			}
191 			else	{
192 				g2.setColor( _stage.getBackgroundColor() );
193 				g2.fillRect( 0, 0, size.width, size.height );
194 			}
195 
196 			Map	actors = _stage.getActors();
197 			if( actors != null )	{
198 				Iterator	itr = actors.values().iterator();
199 				Actor	actor = null;
200 				Image	looks = null;
201 				int	x = 0;
202 				int	y = 0;
203 				while( itr.hasNext() )	{
204 					actor = (Actor)itr.next();
205 					looks = actor.getLooksImage();
206 					if( looks != null )	{
207 						x = computePosition( actor );
208 						y = size.height - looks.getHeight( this );
209 						g2.drawImage( looks, x, y, this );
210 					}
211 				}
212 			}
213 		}
214 		else	{
215 			Image	image = _stage.getSlideImage();
216 			if( image != null )	{
217 				g2.drawImage( image, 0, 0, this );
218 			}
219 			else	{
220 				g2.fillRect( 0, 0, size.width, size.height );
221 			}
222 		}
223 
224 		if( _usingEffect )	{
225 			Effect	effect = (Effect)_effects.get( effectName );
226 			if( effect != null )	{
227 				effect.process( this, _screen, _working );
228 			}
229 			else	{
230 				Logger.error( "[canvas.stage] unsuported effect name. :" + effect );
231 				_screen.setData( _working.getRaster() );
232 				repaint();
233 			}
234 			synchronized( this )	{
235 				try	{
236 					wait( 100 );
237 				}
238 				catch( InterruptedException ie )	{
239 					Logger.debug( "[canvas.stage] interrupted after effect.", ie );
240 				}
241 			}
242 		}
243 		else	{
244 			_screen.setData( _working.getRaster() );
245 			repaint();
246 		}
247 	}
248 
249 	public void paintPageBackground( boolean visiblePage )
250 	{
251 		Graphics2D	g2 = _screen.createGraphics();
252 		g2.drawImage( _working, 0, 0, this );
253 		if( visiblePage )	{
254 			tsukuba_bunko.peko.PekoSystem.getInstance().getCanvasManager().getTextCanvas().paintPageBackground( g2 );
255 		}
256 		g2.dispose();
257 		repaint();
258 	}
259 
260 
261 	/***
262 	 * 立ち位置を計算します。
263 	 * @param	position	立ち位置の文字列表現
264 	 */
265 	private int computePosition( Actor actor )
266 	{
267 		int	halfWidth = actor.getLooksImage().getWidth( this ) / 2;
268 		Dimension	size = getSize( _size );
269 		switch( actor.getPosition() )	{
270 		case Actor.POSITION_CENTER:
271 			return ((int)((float)size.width / 2f)) - halfWidth;
272 		case Actor.POSITION_LEFT:
273 			return ((int)((float)size.width / 4f)) - halfWidth;
274 		case Actor.POSITION_RIGHT:
275 			return ((int)((size.width / 4f) * 3f)) - halfWidth;
276 		default:
277 			return (int)actor.getAbsolutePosition() - halfWidth;
278 		}
279 	}
280 
281 //
282 //	JComponent の実装
283 //
284 	protected void paintComponent( Graphics g )
285 	{
286 		g.drawImage( _screen, 0, 0, this );
287 	}
288 }