/*
* Copyright (c) 2003-onwards Shaven Puppy Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Shaven Puppy' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package worm;
import java.io.Serializable;
import java.nio.ByteBuffer;
import org.lwjgl.util.Color;
import org.lwjgl.util.ReadableColor;
import worm.features.LevelColorsFeature;
import worm.features.LevelFeature;
import worm.screens.GameScreen;
import com.shavenpuppy.jglib.interpolators.LinearInterpolator;
/**
* Attenuated color - blends two ReadableColors together by a factor
*/
public class AttenuatedColor implements ReadableColor, Serializable {
private static final long serialVersionUID = 1L;
/** Attenuation tiles colour name */
public static final String ATTENUATE = "attenuate";
/** Attenuation alpha colour name */
public static final String MAX_ATTENUATION = "maxAttenuation";
/** Attenuation colour */
private static ReadableColor attenuation = new Color();
private ReadableColor color;
private float ratio;
private int tick, update;
private int red, green, blue, alpha;
private int fadeLevel;
private int maxFadeLevel;
private boolean isShadow;
public AttenuatedColor(ReadableColor color) {
this(color, 0, 1, 0.0f, 128, false); // Update attenuation only every 128 RGBA reads or so
}
public AttenuatedColor(ReadableColor color, boolean isShadow) {
this(color, 0, 1, 0.0f, 128, true); // Update attenuation only every 128 RGBA reads or so
}
public AttenuatedColor(ReadableColor color, int fadeLevel, int maxFadeLevel, float ratio, int updateFrequency, boolean isShadow) {
this.color = color;
this.fadeLevel = fadeLevel;
this.maxFadeLevel = maxFadeLevel;
this.isShadow = isShadow;
if (Worm.getGameState() == null || Worm.getGameState().getLevelFeature() == null) {
this.ratio = ratio; // bodge
} else {
this.ratio = (float) (ratio * Worm.getGameState().getLevelFeature().getColors().getColor(MAX_ATTENUATION).getAlpha()/255.0);
}
if (isShadow) {
ratio = Math.min(0.5f, ratio);
}
this.update = updateFrequency;
this.tick = update;
if (update == 0) {
doCalc();
}
}
public void setRatio(float ratio) {
LevelFeature levelFeature = Worm.getGameState().getLevelFeature();
if (levelFeature == null) {
// Not ready yet - probably a result of resizing the game window during a Create Easier Level maneouvre...
return;
}
LevelColorsFeature colors = levelFeature.getColors();
ReadableColor color = colors.getColor(MAX_ATTENUATION);
this.ratio = (float) (ratio * color.getAlpha()/255.0);
if (ratio < 0.0f) {
ratio = 0.0f;
} else if (ratio > 1.0f) {
ratio = 1.0f;
}
if (isShadow) {
ratio = Math.min(0.5f, ratio);
}
tick = update;
}
public void setFade(int fade) {
this.fadeLevel = fade;
maxFadeLevel = 5;
tick = update;
}
private void maybeCalc() {
if (update == 0 && !GameScreen.isDiddlerOpen()) {
return;
}
tick ++;
if (tick >= update) {
tick = 0;
doCalc();
}
}
private void doCalc() {
double ft = ratio * Math.PI * 0.5;
float mf = (float) Math.cos(ft);
float f = 1.0f - mf;
float fade = LinearInterpolator.instance.interpolate(1.0f, 0.0f, (float) fadeLevel / maxFadeLevel);
red = (int) (fade * (color.getRed() * mf + attenuation.getRed() * f));
green = (int) (fade * (color.getGreen() * mf + attenuation.getGreen() * f));
blue = (int) (fade * (color.getBlue() * mf + attenuation.getBlue() * f));
alpha = (int) (color.getAlpha() * mf + attenuation.getAlpha() * f);
}
@Override
public int getAlpha() {
return alpha;
}
@Override
public byte getAlphaByte() {
return (byte) getAlpha();
}
@Override
public int getBlue() {
return blue;
}
@Override
public byte getBlueByte() {
return (byte) getBlue();
}
@Override
public int getGreen() {
return green;
}
@Override
public byte getGreenByte() {
return (byte) getGreen();
}
@Override
public int getRed() {
maybeCalc();
return red;
}
@Override
public byte getRedByte() {
return (byte) getRed();
}
@Override
public void writeABGR(ByteBuffer dest) {
dest.put(getAlphaByte());
dest.put(getBlueByte());
dest.put(getGreenByte());
dest.put(getRedByte());
}
@Override
public void writeARGB(ByteBuffer dest) {
dest.put(getAlphaByte());
dest.put(getRedByte());
dest.put(getGreenByte());
dest.put(getBlueByte());
}
@Override
public void writeBGR(ByteBuffer dest) {
dest.put(getBlueByte());
dest.put(getGreenByte());
dest.put(getRedByte());
}
@Override
public void writeBGRA(ByteBuffer dest) {
dest.put(getBlueByte());
dest.put(getGreenByte());
dest.put(getRedByte());
dest.put(getAlphaByte());
}
@Override
public void writeRGB(ByteBuffer dest) {
dest.put(getRedByte());
dest.put(getGreenByte());
dest.put(getBlueByte());
}
@Override
public void writeRGBA(ByteBuffer dest) {
dest.put(getRedByte());
dest.put(getGreenByte());
dest.put(getBlueByte());
dest.put(getAlphaByte());
}
public static void setAttenuation(ReadableColor attenuation) {
AttenuatedColor.attenuation = attenuation;
}
}