1 /* 2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.scene.shape; 27 28 import com.sun.javafx.geom.BaseBounds; 29 import com.sun.javafx.geom.PickRay; 30 import com.sun.javafx.geom.transform.BaseTransform; 31 import com.sun.javafx.scene.DirtyBits; 32 import com.sun.javafx.scene.NodeHelper; 33 import com.sun.javafx.scene.input.PickResultChooser; 34 import com.sun.javafx.scene.shape.MeshHelper; 35 import com.sun.javafx.scene.shape.MeshViewHelper; 36 import com.sun.javafx.sg.prism.NGMeshView; 37 import com.sun.javafx.sg.prism.NGNode; 38 import javafx.beans.property.ObjectProperty; 39 import javafx.beans.property.SimpleObjectProperty; 40 import javafx.beans.value.ChangeListener; 41 import javafx.beans.value.ObservableValue; 42 import javafx.beans.value.WeakChangeListener; 43 import javafx.scene.Node; 44 45 /** 46 * The {@code MeshView} class defines a surface with the specified 3D 47 * mesh data. 48 * 49 * @since JavaFX 8.0 50 */ 51 public class MeshView extends Shape3D { 52 static { 53 // This is used by classes in different packages to get access to 54 // private and package private methods. 55 MeshViewHelper.setMeshViewAccessor(new MeshViewHelper.MeshViewAccessor() { 56 @Override 57 public NGNode doCreatePeer(Node node) { 58 return ((MeshView) node).doCreatePeer(); 59 } 60 61 @Override 62 public void doUpdatePeer(Node node) { 63 ((MeshView) node).doUpdatePeer(); 64 } 65 66 }); 67 } 68 69 { 70 // To initialize the class helper at the begining each constructor of this class 71 MeshViewHelper.initHelper(this); 72 } 73 74 /** 75 * Creates a new instance of {@code MeshView} class. 76 */ 77 public MeshView() { 78 } 79 80 /** 81 * Creates a new instance of {@code MeshView} class with the specified {@code Mesh} 82 * surface. 83 */ 84 public MeshView(Mesh mesh) { 85 setMesh(mesh); 86 } 87 88 /** 89 * Specifies the 3D mesh data of this {@code MeshView}. 90 * 91 * @defaultValue null 92 */ 93 private ObjectProperty<Mesh> mesh; 94 95 public final void setMesh(Mesh value) { 96 meshProperty().set(value); 97 } 98 99 public final Mesh getMesh() { 100 return mesh == null ? null : mesh.get(); 101 } 102 103 public final ObjectProperty<Mesh> meshProperty() { 104 if (mesh == null) { 105 mesh = new SimpleObjectProperty<Mesh>(MeshView.this, "mesh") { 106 107 private Mesh old = null; 108 private final ChangeListener<Boolean> meshChangeListener = 109 (observable, oldValue, newValue) -> { 110 if (newValue) { 111 NodeHelper.markDirty(MeshView.this, DirtyBits.MESH_GEOM); 112 impl_geomChanged(); 113 } 114 }; 115 private final WeakChangeListener<Boolean> weakMeshChangeListener = 116 new WeakChangeListener(meshChangeListener); 117 118 @Override 119 protected void invalidated() { 120 if (old != null) { 121 old.dirtyProperty().removeListener(weakMeshChangeListener); 122 } 123 Mesh newMesh = get(); 124 if (newMesh != null) { 125 newMesh.dirtyProperty().addListener(weakMeshChangeListener); 126 } 127 NodeHelper.markDirty(MeshView.this, DirtyBits.MESH); 128 NodeHelper.markDirty(MeshView.this, DirtyBits.MESH_GEOM); 129 impl_geomChanged(); 130 old = newMesh; 131 } 132 }; 133 } 134 return mesh; 135 } 136 137 /* 138 * Note: This method MUST only be called via its accessor method. 139 */ 140 private void doUpdatePeer() { 141 NGMeshView peer = NodeHelper.getPeer(this); 142 if (NodeHelper.isDirty(this, DirtyBits.MESH_GEOM) && getMesh() != null) { 143 getMesh().updatePG(); 144 } 145 if (NodeHelper.isDirty(this, DirtyBits.MESH)) { 146 peer.setMesh((getMesh() == null) ? null : getMesh().getPGMesh()); 147 } 148 } 149 150 /* 151 * Note: This method MUST only be called via its accessor method. 152 */ 153 private NGNode doCreatePeer() { 154 return new NGMeshView(); 155 } 156 157 /** 158 * @treatAsPrivate implementation detail 159 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 160 */ 161 @Deprecated 162 @Override 163 public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) { 164 if (getMesh() != null) { 165 bounds = getMesh().computeBounds(bounds); 166 bounds = tx.transform(bounds, bounds); 167 } else { 168 bounds.makeEmpty(); 169 } 170 return bounds; 171 } 172 173 /** 174 * @treatAsPrivate implementation detail 175 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 176 */ 177 @Deprecated 178 @Override 179 protected boolean impl_computeContains(double localX, double localY) { 180 throw new UnsupportedOperationException("Not supported yet."); 181 } 182 183 /** 184 * @treatAsPrivate implementation detail 185 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 186 */ 187 @Override 188 @Deprecated 189 protected boolean impl_computeIntersects(PickRay pickRay, PickResultChooser pickResult) { 190 return MeshHelper.computeIntersects(getMesh(), pickRay, pickResult, this, getCullFace(), true); 191 } 192 193 }