001package com.fs.starfarer.api.impl.campaign.terrain;
002
003import java.awt.Color;
004
005import org.lwjgl.opengl.GL11;
006import org.lwjgl.util.vector.Vector2f;
007
008import com.fs.starfarer.api.Global;
009import com.fs.starfarer.api.campaign.SectorEntityToken;
010import com.fs.starfarer.api.graphics.SpriteAPI;
011import com.fs.starfarer.api.impl.campaign.ids.Factions;
012import com.fs.starfarer.api.impl.campaign.ids.Tags;
013import com.fs.starfarer.api.util.FaderUtil;
014import com.fs.starfarer.api.util.Misc;
015
016public class DebrisPiece {
017
018        public static final float CELL_SIZE = 32;
019        
020        protected SpriteAPI shadowMask;
021        protected SpriteAPI sprite;
022        protected SpriteAPI glow;
023        
024        protected float width;
025        protected float height;
026        protected float radius;
027
028        protected DebrisFieldTerrainPlugin field;
029        
030        protected Vector2f loc = new Vector2f();
031        protected Vector2f vel = new Vector2f();
032        protected float timeLeft = 0f;
033        protected float facing = 0f;
034        protected float angVel = 0f;
035        protected FaderUtil fader = new FaderUtil(0f, 0.2f, 0.2f); // days
036        
037        protected FaderUtil glowBounce;
038        protected FaderUtil glowFader = new FaderUtil(0f, 0.1f, 0.1f);
039        
040        //protected IntervalUtil indCheck = new IntervalUtil(0.0f, 0.2f);
041        protected FaderUtil indFader = new FaderUtil(0f, 0.3f, 0.8f, false, true);
042
043        //protected float indProb = 0.05f;
044        
045        public DebrisPiece(DebrisFieldTerrainPlugin field) {
046                this.field = field;
047                
048                glowBounce =  new FaderUtil(0f, 0.1f + (float) Math.random() * 0.1f, 0.1f + (float) Math.random() * 0.1f); // days
049                glowBounce.setBounce(true, true);
050                glowBounce.fadeIn();
051                
052                if ((float) Math.random() < field.getPieceGlowProbability()) {
053                        glowFader.fadeIn();
054                }
055                
056                sprite = Global.getSettings().getSprite("terrain", "debrisFieldSheet");
057                glow = Global.getSettings().getSprite("terrain", "debrisFieldGlowSheet");
058                
059                
060                float sizeRangeMult = 0.5f + 0.5f * field.params.density;
061                this.width = field.getParams().minSize + 
062                                        (float) Math.random() * sizeRangeMult * (field.getParams().maxSize - field.getParams().minSize);
063                this.height = width;
064                
065                radius = width * 1.41f * 0.5f;
066                
067                float w = sprite.getWidth();
068                float h = sprite.getHeight();
069                int cols = (int) (w / CELL_SIZE);
070                int rows = (int) (h / CELL_SIZE);
071                
072                
073                float cellX = (int) (Math.random() * cols); 
074                float cellY = (int) (Math.random() * rows);
075                
076                float ctw = sprite.getTextureWidth() / (float) cols;
077                float cth = sprite.getTextureHeight() / (float) rows;
078                
079                sprite.setTexX(cellX * ctw);
080                sprite.setTexY(cellY * cth);
081                sprite.setTexWidth(ctw);
082                sprite.setTexHeight(cth);
083                
084                glow.setTexX(cellX * ctw);
085                glow.setTexY(cellY * cth);
086                glow.setTexWidth(ctw);
087                glow.setTexHeight(cth);
088                
089                sprite.setSize(width, height);
090                glow.setSize(width, height);
091                
092                //glow.setColor(new Color(255,165,100,255));
093                glow.setColor(field.getParams().glowColor);
094                
095                shadowMask = Global.getSettings().getSprite("graphics/fx/ship_shadow_mask.png");
096                shadowMask.setSize(width * 1.5f, height * 1.5f);
097                
098                fader.fadeIn();
099                
100                facing = (float) Math.random() * 360f;
101                angVel = (float) Math.random() * 360f - 180f;
102                
103                float spawnRadius = field.params.bandWidthInEngine * field.getExpander().getBrightness();
104                //spawnRadius *= 0.75f;
105                
106                float r = (float) Math.random();
107                r = (float) Math.sqrt(r);
108                float dist = r * spawnRadius;
109                
110                loc = Misc.getUnitVectorAtDegreeAngle((float)Math.random() * 360f);
111                loc.scale(dist);
112                
113                vel = Misc.getUnitVectorAtDegreeAngle((float)Math.random() * 360f);
114                
115                vel = Misc.getPerp(loc);
116                float off = 0.25f;
117                vel.x += off - (float) Math.random() * 0.5f * off;
118                vel.y += off - (float) Math.random() * 0.5f * off;
119                if ((float) Math.random() > 0.5f) {
120                        vel.negate();
121                }
122                Misc.normalise(vel);
123                
124                float speed = 20f + (float) Math.random() * 100f;
125                vel.scale(speed);
126                
127                timeLeft = 1f + (float) Math.random();
128//              if (Math.random() < indProb) {
129//                      indFader.fadeIn();
130//              }
131        }
132        
133        public void render(float alphaMult) {
134
135                //alphaMult *= fader.getBrightness();
136                if (alphaMult <= 0) return;
137                
138                SectorEntityToken entity = field.getEntity();
139                SectorEntityToken lightSource = entity.getLightSource();
140                if (lightSource != null && entity.getLightColor() != null) {
141                        sprite.setColor(entity.getLightColor());
142                } else {
143                        sprite.setColor(Color.white);
144                }
145                                
146                sprite.setAngle(facing - 90);
147                sprite.setNormalBlend();
148                sprite.setAlphaMult(alphaMult * fader.getBrightness());
149                sprite.renderAtCenter(loc.x, loc.y);
150                                
151                if (lightSource != null && !entity.getLightSource().hasTag(Tags.AMBIENT_LS)) {
152                        float w = shadowMask.getWidth() * 1.41f;
153                        float h = w;
154                        
155                        // clear out destination alpha in area we care about
156                        GL11.glColorMask(false, false, false, true);
157                        GL11.glPushMatrix();
158                        GL11.glTranslatef(loc.x, loc.y, 0);
159                        Misc.renderQuadAlpha(0 - w/2f - 1f, 0 - h/2f - 1f, w + 2f, h + 2f, Misc.zeroColor, 0f);
160                        GL11.glPopMatrix();
161                        sprite.setBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);
162                        sprite.renderAtCenter(loc.x, loc.y);
163                        
164                        float lightDir = Misc.getAngleInDegreesStrict(field.getEntity().getLocation(), lightSource.getLocation());
165                        shadowMask.setAlphaMult(alphaMult);
166                        shadowMask.setAngle(lightDir);
167                        shadowMask.setBlendFunc(GL11.GL_ZERO, GL11.GL_SRC_ALPHA);
168                        shadowMask.renderAtCenter(loc.x, loc.y);
169                        
170                        GL11.glColorMask(true, true, true, false);
171                        shadowMask.setBlendFunc(GL11.GL_DST_ALPHA, GL11.GL_ONE_MINUS_DST_ALPHA);
172                        shadowMask.renderAtCenter(loc.x, loc.y);
173                }
174                
175                
176                if (glowFader.getBrightness() > 0) {
177                        glow.setAngle(facing - 90);
178                        glow.setAdditiveBlend();
179                        glow.setAlphaMult(alphaMult * fader.getBrightness() * 
180                                                                        (0.5f + 0.5f * glowBounce.getBrightness()) *
181                                                                        glowFader.getBrightness());
182                        glow.renderAtCenter(loc.x, loc.y);
183                }
184                
185        }
186        
187        public void renderIndicator(float alphaMult) {
188                
189                if (indFader.isFadedOut()) return;
190                alphaMult *= fader.getBrightness();
191                
192                if (alphaMult <= 0) return;
193                
194                
195                
196                GL11.glPushMatrix();
197                GL11.glTranslatef(loc.x, loc.y, 0);
198
199                GL11.glDisable(GL11.GL_TEXTURE_2D);
200                GL11.glEnable(GL11.GL_LINE_SMOOTH);
201                GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
202                
203                float thickness = 1.5f;
204                GL11.glLineWidth(thickness);
205                
206                GL11.glEnable(GL11.GL_BLEND);
207                //GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
208                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
209                
210                //Color color = Global.getSector().getPlayerFaction().getBaseUIColor();
211                Color color = Global.getSector().getFaction(Factions.NEUTRAL).getBaseUIColor();
212                if (field.isScavenged()) {
213                        //color = Misc.getNegativeHighlightColor();
214                        //color = Global.getSector().getFaction(Factions.PIRATES).getDarkUIColor();
215                }
216                
217                float size = width + 5f;
218                float half = size * 0.5f;
219                float corner = size * 0.25f;
220                float x = 0;
221                float y = 0;
222                
223                float b = alphaMult;
224                float f = indFader.getBrightness();
225                float glow = 0;
226                if (f < 0.1f) {
227                        b *= f / 0.1f;
228                } else if (indFader.isFadingIn() && f < 0.4f) {
229                        float p = (f - 0.1f) / (0.4f - 0.1f);
230                        glow = (float) (Math.sin(p * (float) Math.PI * 6f - (float) Math.PI) + 1f) / 2f;
231                        if (glow < 0.5f) {
232                                glow = 0f;
233                        } else {
234                                glow = 1f;
235                        }
236                        glow *= 0.25f;
237                }
238                
239                for (int i = 0; i < 2; i++) {
240                        if (i == 1) {
241                                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
242                                b = glow;
243                        }
244                        if (b <= 0) continue;
245                        
246                        GL11.glBegin(GL11.GL_LINE_STRIP);
247                        Misc.setColor(color, b);
248                        GL11.glVertex2f(x - half, y + half - corner);
249                        GL11.glVertex2f(x - half, y + half);
250                        GL11.glVertex2f(x - half + corner, y + half);
251                        GL11.glEnd();
252                        
253                        GL11.glBegin(GL11.GL_LINE_STRIP);
254                        Misc.setColor(color, b);
255                        GL11.glVertex2f(x + half, y + half - corner);
256                        GL11.glVertex2f(x + half, y + half);
257                        GL11.glVertex2f(x + half - corner, y + half);
258                        GL11.glEnd();
259                        
260                        GL11.glBegin(GL11.GL_LINE_STRIP);
261                        Misc.setColor(color, b);
262                        GL11.glVertex2f(x - half, y - half + corner);
263                        GL11.glVertex2f(x - half, y - half);
264                        GL11.glVertex2f(x - half + corner, y - half);
265                        GL11.glEnd();
266                        
267                        GL11.glBegin(GL11.GL_LINE_STRIP);
268                        Misc.setColor(color, b);
269                        GL11.glVertex2f(x + half, y - half + corner);
270                        GL11.glVertex2f(x + half, y - half);
271                        GL11.glVertex2f(x + half - corner, y - half);
272                        GL11.glEnd();
273                }
274                
275                
276                GL11.glPopMatrix();
277                GL11.glDisable(GL11.GL_LINE_SMOOTH);
278                
279        }
280        
281        
282//      public void renderIndicatorOld(float alphaMult) {
283//              
284//              alphaMult *= fader.getBrightness();
285//              alphaMult *= indFader.getBrightness();
286//              
287//              if (alphaMult <= 0) return;
288//              
289//              
290//              float r = Math.max(10f, radius + 5f);
291//              float lineLength = 10f;
292//              float thickness = 2f;
293//              
294//              float spanRad = (float) Math.PI * 2f;
295//              float arcLength = spanRad * radius;
296//              
297//              float numSegments = (float) Math.ceil(arcLength/lineLength);
298//              if (numSegments < 16) numSegments = 16;
299//              if ((int)numSegments % 4 != 0) {
300//                      numSegments = ((int) numSegments / 4) * 4 + 4;
301//              }
302//              
303//              
304//              float anglePerIter = spanRad / numSegments;
305//              
306//              GL11.glPushMatrix();
307//              GL11.glTranslatef(loc.x, loc.y, 0);
308//
309//              GL11.glDisable(GL11.GL_TEXTURE_2D);
310//              GL11.glEnable(GL11.GL_LINE_SMOOTH);
311//              GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
312//              GL11.glLineWidth(thickness);
313//              
314//              GL11.glEnable(GL11.GL_BLEND);
315//              //GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
316//              GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
317//              
318//              //Color color = Global.getSector().getPlayerFaction().getBaseUIColor();
319//              Color color = Global.getSector().getFaction(Factions.NEUTRAL).getBaseUIColor();
320//              
321//              GL11.glBegin(GL11.GL_LINE_LOOP);
322//              for (float i = 0; i < numSegments + 1; i++) {
323//                      float b = alphaMult;
324//                      Misc.setColor(color, b);
325//                      float theta = anglePerIter * i;
326//                      float cos = (float) Math.cos(theta);
327//                      float sin = (float) Math.sin(theta);
328//                      float x1 = cos * (r - thickness / 2f);
329//                      float y1 = sin * (r - thickness / 2f);
330//                      GL11.glVertex2f(x1, y1);
331//              }
332//              GL11.glEnd();
333//              
334//              
335//              GL11.glPopMatrix();
336//              
337//              GL11.glDisable(GL11.GL_LINE_SMOOTH);
338//              
339//      }
340        
341        
342        public void advance(float days) {
343                fader.advance(days);
344                glowBounce.advance(days);
345                glowFader.advance(days);
346                
347                facing += angVel * days;
348                
349                loc.x += vel.x * days;
350                loc.y += vel.y * days;
351                
352                timeLeft -= days;
353                if (timeLeft < 0) {
354                        fader.fadeOut();
355                }
356                
357//              indCheck.advance(days);
358//              if (indCheck.intervalElapsed() && Math.random() < indProb) {
359//                      indFader.fadeIn();
360//              }
361                indFader.advance(days);
362        }
363        
364        public void showIndicator() {
365                if (indFader.isIdle()) {
366                        float in = 0.3f;
367                        float out = 0.3f + 0.7f * (float) Math.random();
368                        indFader.setDuration(in, out);
369                }
370                indFader.fadeIn();
371        }
372        
373        public boolean hasIndicator() {
374                return !indFader.isIdle();
375        }
376        
377        
378        public boolean isDone() {
379                return fader.isFadedOut();
380        }
381
382        public FaderUtil getGlowFader() {
383                return glowFader;
384        }
385        
386        
387}
388
389
390
391
392
393
394
395
396
397
398
399
400
401