/***********************************************************************
* mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.components.visibleComponents;
import org.mt4j.components.MTComponent;
import org.mt4j.components.clipping.Clip;
import org.mt4j.components.clipping.FillPaint;
import org.mt4j.util.MT4jSettings;
import org.mt4j.util.MTColor;
import org.mt4j.util.camera.Icamera;
import org.mt4j.util.opengl.GLMaterial;
import processing.core.PApplet;
import processing.core.PGraphics;
/**
* The Class AbstractVisibleComponent. Abstract class for creating visible
* components. It provides methods for storing and changing style information, like
* the fill- and stroke color.
* @author Christopher Ruff
*/
public abstract class AbstractVisibleComponent extends MTComponent {
/** The style info. */
private StyleInfo styleInfo;
/** The fill paint. */
private FillPaint fillPaint;
/**
* Instantiates a new abstract visible component.
*
* @param pApplet the applet
*/
public AbstractVisibleComponent(PApplet pApplet) {
this(pApplet,"unnamed visible component", /*null,*/ null);
}
/**
* Instantiates a new abstract visible component.
*
* @param pApplet the applet
* @param globalCamera the global camera
* @param objectCamera the object camera
*/
public AbstractVisibleComponent(PApplet pApplet, Icamera globalCamera, Icamera objectCamera) {
this(pApplet,"unnamed visible component",/* globalCamera,*/ objectCamera);
}
/**
* Instantiates a new abstract visible component.
*
* @param pApplet the applet
* @param name the name
* @param objectCamera the object camera
*/
public AbstractVisibleComponent(PApplet pApplet, String name, /*Icamera globalCamera,*/ Icamera objectCamera) {
super(pApplet, name, /*globalCamera,*/ objectCamera);
//DEFAULTS
styleInfo = new StyleInfo();
}
/**
* Gets the fill paint.
*
* @return the fill paint
*/
public FillPaint getFillPaint() {
return fillPaint;
}
/**
* Sets the fill paint.
*
* @param fillPaint the new fill paint
*/
public void setFillPaint(FillPaint fillPaint) {
this.fillPaint = fillPaint;
this.fillPaint.setShape(this);
}
@Override
public void preDraw(PGraphics graphics) {
super.preDraw(graphics);
//Apply material if set
if (this.getMaterial() != null){
this.getMaterial().apply();
}
//Apply the stencil buffer stettings for
//drawing the gradient shape
//Also DONT draw the outline here because its
//anti aliasing will be ruined by the stencil
//Instead we draw the outline over the gradient
//in postDraw() method
savedNoStrokeSetting = this.isNoStroke();
if (this.getFillPaint() != null){
FillPaint fillPaint = this.getFillPaint();
//Force drawing stencil shape without stroke
this.setNoStroke(true);
fillPaint.pre(graphics);
}
//FIXME outline gets drawn twice if gradient + childClipmask
//FIXME TEST //Draw without stroke because the stencil
//will ruin the antialiased stroke line
//so we draw here without stroke but after all the clipped
//children are drawn we draw the stroke outline over it all
//in postDrawChildren()
if (this.getChildClip() != null){
if (!this.isNoStroke()){
this.setNoStroke(true);
}
}
}
/** The saved no stroke setting. */
private boolean savedNoStrokeSetting;
@Override
public void postDraw(PGraphics graphics) {
super.postDraw(graphics);
//Draw gradient
if (this.getFillPaint() != null){
FillPaint g = this.getFillPaint();
//Draw gradient over shape!
g.post(graphics);
boolean savedNoFillSetting = this.isNoFill();
//Draw shape outlines over gradient
if (!savedNoStrokeSetting){
this.setNoStroke(false);
this.setNoFill(true);
this.drawComponent(graphics);
this.setNoFill(savedNoFillSetting);
}
this.setNoStroke(savedNoStrokeSetting);
}
//FIXME wie wieder normalzustand?
// if (this.getMaterial() != null){
//
// }
}
/* (non-Javadoc)
* @see org.mt4j.components.MTComponent#postDrawChildren(processing.core.PGraphics)
*/
@Override
public void postDrawChildren(PGraphics g) {
//FIXME this is a hack to draw the outline of the shape
//over the clipped children, to not process the clipmask
//in the superclass we set it to null temporary
Clip saved = this.getChildClip();
if (saved != null){
saved.disableClip(g);
//Draw shape outline over everything for an antialiased outline
if (!savedNoStrokeSetting){
boolean noFillSetting = this.isNoFill();
this.setNoFill(true);
this.setNoStroke(false);
this.drawComponent(g);
this.setNoFill(noFillSetting);
this.setNoStroke(savedNoStrokeSetting);
}
//Set mask null because the superclass
//implementation would also try to pop the stencil stack value
this.setChildClip(null);
}
super.postDrawChildren(g);
if (saved != null){
this.setChildClip(saved);
}
}
/**
* Gets the style info.
*
* @return the styleInfo
*/
public StyleInfo getStyleInfo() {
return styleInfo;
}
/**
* Sets the style info.
*
* @param styleInfo the styleInfo to set
*/
public void setStyleInfo(StyleInfo styleInfo) {
this.styleInfo = styleInfo;
this.applyStyle();
}
/**
* Apply style.
*/
protected void applyStyle(){
//TODO apply all styleInfo settings to the component
this.setFillColor(this.getStyleInfo().getFillColor());
this.setStrokeColor(this.getStyleInfo().getStrokeColor());
this.setLineStipple(this.getStyleInfo().getLineStipple());
this.setMaterial(this.getStyleInfo().getMaterial());
this.setNoFill(this.getStyleInfo().isNoFill());
this.setNoStroke(this.getStyleInfo().isNoStroke());
this.setFillDrawMode(this.getStyleInfo().getFillDrawMode());
}
// TODO wirklich protected machen? dann kann man im zweifeln nicht nur diese eine komponente fragen ob sie schnittpunkt hat,
// weil auch kinder miteinbezogen werden bei call von public getInterSectionpoint()
// abstract public Vector3D getIntersectionLocal(Ray ray);
// abstract protected boolean intersectsComponentWithRay(Ray ray);
abstract public void drawComponent(PGraphics g);
// abstract protected boolean componentContainsPointLocal(Vector3D testPoint);
// /**
// * Sets the fill color.
// *
// * @param r the r
// * @param g the g
// * @param b the b
// * @param a the a
// *
// * @see org.mt4j.components.visibleComponents.StyleInfo#setFillColor(float, float, float, float)
// */
// public void setFillColor(float r, float g, float b, float a) {
// styleInfo.setFillColor(r, g, b, a);
// }
/**
* Sets the fill color.
*
* @param fillColor the new fill color
*/
public void setFillColor(MTColor fillColor){
this.styleInfo.setFillColor(fillColor);
}
/**
* Gets the fill color.
*
* @return the fill color
*/
public MTColor getFillColor(){
return styleInfo.getFillColor();
}
// /**
// * Sets the stroke color.
// *
// * @param r the r
// * @param g the g
// * @param b the b
// * @param a the a
// *
// * @see org.mt4j.components.visibleComponents.StyleInfo#setStrokeColor(float, float, float, float)
// */
// public void setStrokeColor(float r, float g, float b, float a) {
// styleInfo.setStrokeColor(r, g, b, a);
// }
/**
* Sets the stroke color.
*
* @param strokeColor the new stroke color
*/
public void setStrokeColor(MTColor strokeColor){
this.styleInfo.setStrokeColor(strokeColor);
}
/**
* Gets the stroke color.
*
* @return the stroke color
*/
public MTColor getStrokeColor(){
return styleInfo.getStrokeColor();
}
/**
* Gets the stroke weight.
*
* @return the stroke weight
*
* @see org.mt4j.components.visibleComponents.StyleInfo#getStrokeWeight()
*/
public float getStrokeWeight() {
return styleInfo.getStrokeWeight();
}
/**
* Checks if is draw smooth.
*
* @return true, if checks if is draw smooth
*
* @see org.mt4j.components.visibleComponents.StyleInfo#isDrawSmooth()
*/
public boolean isDrawSmooth() {
return styleInfo.isDrawSmooth();
}
/**
* Checks if is no fill.
*
* @return true, if checks if is no fill
*
* @see org.mt4j.components.visibleComponents.StyleInfo#isNoFill()
*/
public boolean isNoFill() {
return styleInfo.isNoFill();
}
/**
* Checks if is no stroke.
*
* @return true, if checks if is no stroke
*
* @see org.mt4j.components.visibleComponents.StyleInfo#isNoStroke()
*/
public boolean isNoStroke() {
return styleInfo.isNoStroke();
}
/**
* Sets the draw smooth.
*
* @param drawSmooth the draw smooth
*
* @see org.mt4j.components.visibleComponents.StyleInfo#setDrawSmooth(boolean)
*/
public void setDrawSmooth(boolean drawSmooth) {
styleInfo.setDrawSmooth(drawSmooth);
}
/**
* Sets the no fill.
*
* @param noFill the no fill
*
* @see org.mt4j.components.visibleComponents.StyleInfo#setNoFill(boolean)
*/
public void setNoFill(boolean noFill) {
styleInfo.setNoFill(noFill);
}
/**
* Sets the no stroke.
*
* @param noStroke the no stroke
*
* @see org.mt4j.components.visibleComponents.StyleInfo#setNoStroke(boolean)
*/
public void setNoStroke(boolean noStroke) {
styleInfo.setNoStroke(noStroke);
}
/**
* Sets the stroke weight.
*
* @param strokeWeight the stroke weight
*
* @see org.mt4j.components.visibleComponents.StyleInfo#setStrokeWeight(float)
*/
public void setStrokeWeight(float strokeWeight) {
styleInfo.setStrokeWeight(strokeWeight);
}
/**
* Gets the fill draw mode.
*
* @return the fill draw mode
*/
public int getFillDrawMode() {
return styleInfo.getFillDrawMode();
}
/**
* Sets the draw mode which will be used for creating display lists.
* <br>Modes are the opengl draw modes, e.g. GL_POLYGON, GL_TRIANGLE_FAN, GL_LINES etc.
* <br>Default mode is GL_TRIANGLE_FAN
*
* @param fillDrawMode the fill draw mode
*/
public void setFillDrawMode(int fillDrawMode) {
styleInfo.setFillDrawMode(fillDrawMode);
}
/**
* Sets a line stipple pattern for drawing outlines.
* <b><br>Only supported when using the OpenGL renderer!
* <br>Example: shape.setLineStipple((short)0xDDDD);
* <br>Default value is '0'. No stipple pattern is used then.
*
* @param stipplePattern the stipple pattern
*/
public void setLineStipple(short stipplePattern){
if (!MT4jSettings.getInstance().isOpenGlMode()){
System.err.println("Cant set line stipple pattern if not using the OpenGL renderer. " + (this));
}
styleInfo.setLineStipple(stipplePattern);
}
/**
* Gets the line stipple.
*
* @return the line stipple
*/
public short getLineStipple() {
return styleInfo.getLineStipple();
}
/**
* Sets the material used by opengl lightning.
*
* @param material the new material
*/
public void setMaterial(GLMaterial material){
this.styleInfo.setMaterial(material);
}
/**
* Gets the material.
*
* @return the material
*/
public GLMaterial getMaterial(){
return this.styleInfo.getMaterial();
}
}