/*
JWildfire - an image and animation processor written in Java
Copyright (C) 1995-2013 Andreas Maschke
This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this software;
if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.create.tina.mutagen;
import static org.jwildfire.base.mathlib.MathLib.EPSILON;
import java.util.ArrayList;
import java.util.List;
import org.jwildfire.base.Tools;
import org.jwildfire.create.tina.base.Layer;
import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.variation.VariationFunc;
public class RandomParamMutation implements Mutation {
@Override
public void execute(Layer pLayer) {
setRandomFlameProperty(pLayer, 6.0 * (0.25 + 0.75 * Math.random()));
setRandomFlameProperty(pLayer, 5.0 * (0.25 + 0.75 * Math.random()));
setRandomFlameProperty(pLayer, 2.0 * (0.25 + 0.75 * Math.random()));
}
private static List<String> BLACKLIST;
static {
BLACKLIST = new ArrayList<String>();
BLACKLIST.add("truchet");
}
public void setRandomFlameProperty(Layer pLayer, double pAmount) {
List<VariationFunc> variations = new ArrayList<VariationFunc>();
for (XForm xForm : pLayer.getXForms()) {
addVariations(variations, xForm);
}
for (XForm xForm : pLayer.getFinalXForms()) {
addVariations(variations, xForm);
}
filterVariations(variations);
if (variations.size() > 0) {
int idx = (int) (Math.random() * variations.size());
VariationFunc var = variations.get(idx);
int pIdx = (int) (Math.random() * var.getParameterNames().length);
Object oldVal = var.getParameterValues()[pIdx];
if (oldVal instanceof Integer) {
int o = (Integer) oldVal;
int da = Tools.FTOI(pAmount);
if (da < 1) {
da = 1;
}
if (o >= 0) {
o += da;
}
else {
o -= da;
}
var.setParameter(var.getParameterNames()[pIdx], o);
}
else if (oldVal instanceof Double) {
double o = (Double) oldVal;
if (o < EPSILON || Math.random() < 0.3) {
if (o >= 0) {
o += 0.1 * pAmount;
}
else {
o -= 0.1 * pAmount;
}
}
else {
if (o >= 0) {
o += o / 100.0 * pAmount;
}
else {
o -= o / 100.0 * pAmount;
}
}
var.setParameter(var.getParameterNames()[pIdx], o);
}
}
}
private void filterVariations(List<VariationFunc> variations) {
int idx = 0;
while (idx < variations.size()) {
if (BLACKLIST.indexOf(variations.get(idx).getName().toLowerCase()) >= 0) {
variations.remove(idx);
}
else {
idx++;
}
}
}
private void addVariations(List<VariationFunc> pVariations, XForm pXForm) {
if (pXForm.getVariationCount() > 0) {
for (int i = 0; i < pXForm.getVariationCount(); i++) {
VariationFunc var = pXForm.getVariation(i).getFunc();
if (var.getParameterNames() != null && var.getParameterNames().length > 0) {
pVariations.add(var);
}
}
}
}
}