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; 027 028import com.sun.javafx.collections.TrackableObservableList; 029import com.sun.javafx.geom.BaseBounds; 030import com.sun.javafx.geom.BoxBounds; 031import com.sun.javafx.geom.transform.Affine3D; 032import com.sun.javafx.geom.transform.BaseTransform; 033import com.sun.javafx.jmx.MXNodeAlgorithm; 034import com.sun.javafx.jmx.MXNodeAlgorithmContext; 035import com.sun.javafx.scene.DirtyBits; 036import com.sun.javafx.sg.PGLightBase; 037import com.sun.javafx.tk.Toolkit; 038import javafx.application.ConditionalFeature; 039import javafx.application.Platform; 040import javafx.beans.InvalidationListener; 041import javafx.beans.Observable; 042import javafx.beans.property.BooleanProperty; 043import javafx.beans.property.ObjectProperty; 044import javafx.beans.property.SimpleBooleanProperty; 045import javafx.beans.property.SimpleObjectProperty; 046import javafx.collections.ListChangeListener.Change; 047import javafx.collections.ObservableList; 048import javafx.scene.paint.Color; 049import javafx.scene.shape.Shape3D; 050import sun.util.logging.PlatformLogger; 051 052/** 053 * The {@code LightBase} class provides definitions of common properties for 054 * objects that represent a form of Light source. These properties 055 * include: 056 * <ul> 057 * <li>The color that defines color of the light source. 058 * </ul> 059 * 060 * Note that this is a conditional feature. See 061 * {@link javafx.application.ConditionalFeature#SCENE3D ConditionalFeature.SCENE3D} 062 * for more information. 063 * 064 * @since JavaFX 8 065 */ 066public abstract class LightBase extends Node { 067 068 private Affine3D localToSceneTx = new Affine3D(); 069 070 /** 071 * Creates a new instance of {@code LightBase} class with a default Color.WHITE light source. 072 */ 073 protected LightBase() { 074 this(Color.WHITE); 075 } 076 077 /** 078 * Creates a new instance of {@code LightBase} class using the specified color. 079 * 080 * @param color the color of the light source 081 */ 082 protected LightBase(Color color) { 083 if (!Platform.isSupported(ConditionalFeature.SCENE3D)) { 084 String logname = LightBase.class.getName(); 085 PlatformLogger.getLogger(logname).warning("System can't support " 086 + "ConditionalFeature.SCENE3D"); 087 } 088 089 setColor(color); 090 this.localToSceneTransformProperty().addListener(new InvalidationListener() { 091 @Override 092 public void invalidated(Observable observable) { 093 impl_markDirty(DirtyBits.NODE_LIGHT_TRANSFORM); 094 } 095 }); 096 } 097 098 /** 099 * Specifies the color of light source. 100 * 101 * @defaultValue null 102 */ 103 private ObjectProperty<Color> color; 104 105 public final void setColor(Color value) { 106 colorProperty().set(value); 107 } 108 109 public final Color getColor() { 110 return color == null ? null : color.get(); 111 } 112 113 public final ObjectProperty<Color> colorProperty() { 114 if (color == null) { 115 color = new SimpleObjectProperty<Color>(LightBase.this, "color") { 116 @Override 117 protected void invalidated() { 118 impl_markDirty(DirtyBits.NODE_LIGHT); 119 } 120 }; 121 } 122 return color; 123 } 124 125 /** 126 * Defines the light on or off. 127 * 128 * @defaultValue true 129 */ 130 private BooleanProperty lightOn; 131 132 public final void setLightOn(boolean value) { 133 lightOnProperty().set(value); 134 } 135 136 public final boolean isLightOn() { 137 return lightOn == null ? true : lightOn.get(); 138 } 139 140 public final BooleanProperty lightOnProperty() { 141 if (lightOn == null) { 142 lightOn = new SimpleBooleanProperty(LightBase.this, "lightOn", true) { 143 @Override 144 protected void invalidated() { 145 impl_markDirty(DirtyBits.NODE_LIGHT); 146 } 147 }; 148 } 149 return lightOn; 150 } 151 152 private ObservableList<Node> scope; 153 154 /** 155 * Gets the list of nodes that specifies the 156 * hierarchical scope of this Light. If the scope list is empty, 157 * the Light node has universe scope: all nodes under it's scene 158 * are affected by it. If the scope list is non-empty, only those 159 * 3D Shape nodes in the scope list and under the Group nodes in the 160 * scope list are affected by this Light node. 161 */ 162 public ObservableList<Node> getScope() { 163 if (scope == null) { 164 scope = new TrackableObservableList<Node>() { 165 166 @Override 167 protected void onChanged(Change<Node> c) { 168 impl_markDirty(DirtyBits.NODE_LIGHT); 169 while (c.next()) { 170 for (Node node : c.getRemoved()) { 171 // Update the removed nodes 172 if (node instanceof Parent || node instanceof Shape3D) { 173 node.impl_markDirty(DirtyBits.NODE_CONTENTS); 174 } 175 } 176 for (Node node : c.getAddedSubList()) { 177 if (node instanceof Parent || node instanceof Shape3D) { 178 node.impl_markDirty(DirtyBits.NODE_CONTENTS); 179 } 180 } 181 } 182 } 183 }; 184 } 185 return scope; 186 } 187 188 @Override 189 void scenesChanged(final Scene newScene, final SubScene newSubScene, 190 final Scene oldScene, final SubScene oldSubScene) { 191 // This light is owned by the Scene/SubScene, and thus must change 192 // accordingly. Note lights can owned by either a Scene or SubScene, 193 // but not both. 194 if (oldSubScene != null) { 195 oldSubScene.removeLight(this); 196 } else if (oldScene != null) { 197 oldScene.removeLight(this); 198 } 199 if (newSubScene != null) { 200 newSubScene.addLight(this); 201 } else if (newScene != null) { 202 newScene.addLight(this); 203 } 204 } 205 206 /** 207 * @treatAsPrivate implementation detail 208 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 209 */ 210 @Deprecated 211 @Override 212 public void impl_updatePG() { 213 super.impl_updatePG(); 214 PGLightBase pgLightBase = (PGLightBase) impl_getPGNode(); 215 if (impl_isDirty(DirtyBits.NODE_LIGHT)) { 216 pgLightBase.setColor((getColor() == null) ? null 217 : Toolkit.getPaintAccessor().getPlatformPaint(getColor())); 218 pgLightBase.setLightOn(isLightOn()); 219 220 if (scope != null) { 221 if (getScope().isEmpty()) { 222 pgLightBase.setScope(null); 223 } else { 224 Object ngList[] = new Object[getScope().size()]; 225 for (int i = 0; i < scope.size(); i++) { 226 Node n = scope.get(i); 227 ngList[i] = n.impl_getPGNode(); 228 } 229 pgLightBase.setScope(ngList); 230 } 231 } 232 } 233 234 if (impl_isDirty(DirtyBits.NODE_LIGHT_TRANSFORM)) { 235 localToSceneTx.setToIdentity(); 236 getLocalToSceneTransform().impl_apply(localToSceneTx); 237 // TODO: 3D - For now, we are treating the scene as world. This may need to change 238 // for the fixed eye position case. 239 pgLightBase.setWorldTransform(localToSceneTx); 240 } 241 } 242 243 /** 244 * @treatAsPrivate implementation detail 245 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 246 */ 247 @Deprecated 248 @Override 249 public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) { 250 // TODO: 3D - Check is this the right default 251 return new BoxBounds(); 252 } 253 254 /** 255 * @treatAsPrivate implementation detail 256 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 257 */ 258 @Deprecated 259 @Override 260 protected boolean impl_computeContains(double localX, double localY) { 261 // TODO: 3D - Check is this the right default 262 return false; 263 } 264 265 /** 266 * @treatAsPrivate implementation detail 267 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 268 */ 269 @Deprecated 270 @Override 271 public Object impl_processMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) { 272 throw new UnsupportedOperationException("Not supported yet."); 273 } 274 275}