Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.shape;
027
028import com.sun.javafx.geom.BaseBounds;
029import com.sun.javafx.geom.BoxBounds;
030import com.sun.javafx.geom.transform.BaseTransform;
031import com.sun.javafx.jmx.MXNodeAlgorithm;
032import com.sun.javafx.jmx.MXNodeAlgorithmContext;
033import com.sun.javafx.scene.DirtyBits;
034import com.sun.javafx.sg.PGPhongMaterial;
035import com.sun.javafx.sg.PGShape3D;
036import javafx.application.ConditionalFeature;
037import javafx.application.Platform;
038import javafx.beans.property.ObjectProperty;
039import javafx.beans.property.SimpleObjectProperty;
040import javafx.beans.value.ChangeListener;
041import javafx.beans.value.ObservableValue;
042import javafx.scene.Node;
043import javafx.scene.paint.Material;
044import javafx.scene.paint.PhongMaterial;
045import sun.util.logging.PlatformLogger;
046
047
048/**
049 * The {@code Shape3D} base class provides definitions of common properties for
050 * objects that represent some form of 3D geometric shape.  These properties
051 * include:
052 * <ul>
053 * <li>The {@link Material} to be applied to the fillable interior of the
054 * shape or the outline of the shape (see {@link #setMaterial}).
055 * <li>The draw model properties that defines how to render its geometry (see {@link #setDrawMode}).
056 * <li>The face culling properties that defines which face to cull (see {@link #setCullFace}).
057 * </ul>
058 *
059 * Note that this is a conditional feature. See
060 * {@link javafx.application.ConditionalFeature#SCENE3D ConditionalFeature.SCENE3D}
061 * for more information.
062 * 
063 * @since JavaFX 8
064 */
065public abstract class Shape3D extends Node {
066    // NOTE: Need a way to specify shape tessellation resolution, may use metric relate to window resolution
067    // Will not support dynamic refinement in FX8
068    
069    // TODO: 3D - May provide user convenient utility to compose images in a single image for shapes such as Box or Cylinder
070
071    private static final PhongMaterial DEFAULT_MATERIAL = new PhongMaterial();
072    
073    protected Shape3D() {
074        if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
075            String logname = Shape3D.class.getName();
076            PlatformLogger.getLogger(logname).warning("System can't support "
077                                                      + "ConditionalFeature.SCENE3D");
078        }
079    }
080
081    PredefinedMeshManager manager = PredefinedMeshManager.getInstance();
082    int key = 0;
083
084    /**
085     * Defines the material this {@code Shape3D}.
086     * The default material is null. If {@code Material} is null, a PhongMaterial
087     * with a diffuse color of Color.LIGHTGRAY is used for rendering.
088     *
089     * @defaultValue null
090     */
091    private ObjectProperty<Material> material;
092
093    public final void setMaterial(Material value) {
094        materialProperty().set(value);
095    }
096
097    public final Material getMaterial() {
098        return material == null ? null : material.get();
099    }
100
101    private final ChangeListener<Boolean> materialListener = new ChangeListener<Boolean>() {
102        @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
103            if (newValue) {
104                impl_markDirty(DirtyBits.MATERIAL_PROPERTY);
105                //impl_geomChanged();
106            }
107        }
108    };
109 
110    public final ObjectProperty<Material> materialProperty() {
111        if (material == null) {
112            material = new SimpleObjectProperty<Material>(Shape3D.this,
113                    "material") {
114
115                private Material old = null;
116                @Override protected void invalidated() {
117                    if (old != null) {
118                        old.impl_dirtyProperty().removeListener(materialListener);
119                    }
120                    Material newMaterial = get();
121                    if (newMaterial != null) {
122                        newMaterial.impl_dirtyProperty().addListener(materialListener);
123                    }
124                    impl_markDirty(DirtyBits.MATERIAL);
125                    impl_geomChanged();
126                    old = newMaterial;
127                }
128            };
129        }
130        return material;
131    }
132
133    /**
134     * Defines the drawMode this {@code Shape3D}.
135     *
136     * @defaultValue DrawMode.FILL
137     */
138    private ObjectProperty<DrawMode> drawMode;
139
140    public final void setDrawMode(DrawMode value) {
141        drawModeProperty().set(value);
142    }
143
144    public final DrawMode getDrawMode() {
145        return drawMode == null ? DrawMode.FILL : drawMode.get();
146    }
147
148    public final ObjectProperty<DrawMode> drawModeProperty() {
149        if (drawMode == null) {
150            drawMode = new SimpleObjectProperty<DrawMode>(Shape3D.this,
151                    "drawMode", DrawMode.FILL) {
152
153                @Override
154                protected void invalidated() {
155                    impl_markDirty(DirtyBits.NODE_DRAWMODE);
156                }
157            };
158        }
159        return drawMode;
160    }  
161
162    /**
163     * Defines the drawMode this {@code Shape3D}.
164     *
165     * @defaultValue CullFace.BACK
166     */
167    private ObjectProperty<CullFace> cullFace;
168
169    public final void setCullFace(CullFace value) {
170        cullFaceProperty().set(value);
171    }
172
173    public final CullFace getCullFace() {
174        return cullFace == null ? CullFace.BACK : cullFace.get();
175    }
176
177    public final ObjectProperty<CullFace> cullFaceProperty() {
178        if (cullFace == null) {
179            cullFace = new SimpleObjectProperty<CullFace>(Shape3D.this,
180                    "cullFace", CullFace.BACK) {
181
182                @Override
183                protected void invalidated() {
184                    impl_markDirty(DirtyBits.NODE_CULLFACE);
185                }
186            };
187        }
188        return cullFace;
189    }  
190
191    /**
192     * @treatAsPrivate implementation detail
193     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
194     */
195    @Deprecated
196    @Override
197    public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
198        // TODO: 3D - Evaluate this logic
199        return new BoxBounds(0, 0, 0, 0, 0, 0);
200    }
201
202    /**
203     * @treatAsPrivate implementation detail
204     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
205     */
206    @Deprecated
207    @Override
208    protected boolean impl_computeContains(double localX, double localY) {
209        return false;
210    }
211
212    /**
213     * @treatAsPrivate implementation detail
214     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
215     */
216    @Deprecated
217    @Override
218    public void impl_updatePG() {
219        super.impl_updatePG();
220
221        // TODO: 3D - Why do we have separate dirty bits for MATERIAL
222        // and MATERIAL_PROPERTY ?
223        Material material = getMaterial();
224        if (impl_isDirty(DirtyBits.MATERIAL_PROPERTY) && material != null) {
225            material.impl_updatePG();
226        }
227        PGShape3D pgShape3D = (PGShape3D) impl_getPGNode();
228        if (impl_isDirty(DirtyBits.MATERIAL)) {
229            if (material != null) {
230                material.impl_updatePG(); // new material should be updated
231                pgShape3D.setMaterial((PGPhongMaterial) material.impl_getPGMaterial());
232            } else {
233                DEFAULT_MATERIAL.impl_updatePG();
234                pgShape3D.setMaterial(DEFAULT_MATERIAL.impl_getPGMaterial());
235            }
236        }
237        if (impl_isDirty(DirtyBits.NODE_DRAWMODE)) {
238            pgShape3D.setDrawMode(getDrawMode());
239        }
240        if (impl_isDirty(DirtyBits.NODE_CULLFACE)) {
241            pgShape3D.setCullFace(getCullFace());
242        }
243    }
244
245    /**
246     * @treatAsPrivate implementation detail
247     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
248     */
249    @Deprecated
250    @Override
251    public Object impl_processMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
252        throw new UnsupportedOperationException("Not supported yet.");
253    }
254    
255}