Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 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.effect; 027 028import javafx.beans.Observable; 029import javafx.beans.property.DoubleProperty; 030import javafx.beans.property.DoublePropertyBase; 031import javafx.beans.property.ObjectProperty; 032import javafx.beans.property.ObjectPropertyBase; 033import javafx.scene.Node; 034 035import com.sun.javafx.Utils; 036import com.sun.javafx.effect.EffectDirtyBits; 037import com.sun.javafx.effect.EffectUtils; 038import com.sun.javafx.geom.BaseBounds; 039import com.sun.javafx.geom.transform.BaseTransform; 040import com.sun.javafx.scene.BoundsAccessor; 041import com.sun.scenario.effect.PhongLighting; 042 043/** 044 * An effect that simulates a light source shining on the given content, 045 * which can be used to give flat objects a more realistic, three-dimensional 046 * appearance. 047 * 048 * <p> 049 * Example: 050 * <pre><code> 051 * Light.Distant light = new Light.Distant(); 052 * light.setAzimuth(-135.0); 053 * 054 * Lighting lighting = new Lighting(); 055 * lighting.setLight(light); 056 * lighting.setSurfaceScale(5.0); 057 * 058 * Text text = new Text(); 059 * text.setText("JavaFX!"); 060 * text.setFill(Color.STEELBLUE); 061 * text.setFont(Font.font(null, FontWeight.BOLD, 60)); 062 * text.setX(10.0); 063 * text.setY(10.0); 064 * text.setTextOrigin(VPos.TOP); 065 * 066 * text.setEffect(lighting); 067 * </pre></code> 068 * <p> The code above produces the following: </p> 069 * <p> 070 * <img * src="doc-files/lighting.png"/> 071 * </p> 072 */ 073public class Lighting extends Effect { 074 @Override 075 com.sun.scenario.effect.PhongLighting impl_createImpl() { 076 return new PhongLighting(getLightInternal().impl_getImpl()); 077 }; 078 079 /** 080 * Creates a new instance of Lighting with default parameters. 081 */ 082 public Lighting() { 083 Shadow shadow = new Shadow(); 084 shadow.setRadius(10.0f); 085 setBumpInput(shadow); 086 } 087 088 /** 089 * Creates a new instance of Lighting with the specified light. 090 * @param light the light source for this {@code Lighting} effect 091 */ 092 public Lighting(Light light) { 093 Shadow shadow = new Shadow(); 094 shadow.setRadius(10.0f); 095 setBumpInput(shadow); 096 setLight(light); 097 } 098 099 private final Light defaultLight = new Light.Distant(); 100 101 /** 102 * The light source for this {@code Lighting} effect. 103 */ 104 private ObjectProperty<Light> light = new ObjectPropertyBase<Light>(new Light.Distant()) { 105 @Override 106 public void invalidated() { 107 markDirty(EffectDirtyBits.EFFECT_DIRTY); 108 effectBoundsChanged(); 109 } 110 111 @Override 112 public Object getBean() { 113 return Lighting.this; 114 } 115 116 @Override 117 public String getName() { 118 return "light"; 119 } 120 }; 121 122 123 public final void setLight(Light value) { 124 lightProperty().set(value); 125 } 126 127 public final Light getLight() { 128 return light.get(); 129 } 130 131 public final ObjectProperty<Light> lightProperty() { 132 return light; 133 } 134 135 private final LightChangeListener lightChangeListener = new LightChangeListener(); 136 137 /** 138 * 139 * @treatAsPrivate implementation detail 140 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 141 */ 142 @Deprecated 143 @Override 144 public Effect impl_copy() { 145 Lighting lighting = new Lighting(this.getLight()); 146 lighting.setBumpInput(this.getBumpInput()); 147 lighting.setContentInput(this.getContentInput()); 148 lighting.setDiffuseConstant(this.getDiffuseConstant()); 149 lighting.setSpecularConstant(this.getSpecularConstant()); 150 lighting.setSpecularExponent(this.getSpecularExponent()); 151 lighting.setSurfaceScale(this.getSurfaceScale()); 152 return lighting; 153 } 154 private class LightChangeListener extends EffectChangeListener { 155 Light light; 156 157 public void register(Light value) { 158 light = value; 159 super.register(light == null ? null : light.effectDirtyProperty()); 160 } 161 162 @Override 163 public void invalidated(Observable valueModel) { 164 if (light.impl_isEffectDirty()) { 165 markDirty(EffectDirtyBits.EFFECT_DIRTY); 166 effectBoundsChanged(); 167 } 168 } 169 }; 170 /** 171 * The optional bump map input. 172 * If not specified, a bump map will be automatically generated 173 * from the default input. 174 * If set to {@code null}, or left unspecified, a graphical image of 175 * the {@code Node} to which the {@code Effect} is attached will be 176 * used to generate a default bump map. 177 * @defaultValue a Shadow effect with a radius of 10 178 */ 179 private ObjectProperty<Effect> bumpInput; 180 181 182 public final void setBumpInput(Effect value) { 183 bumpInputProperty().set(value); 184 } 185 186 public final Effect getBumpInput() { 187 return bumpInput == null ? null : bumpInput.get(); 188 } 189 190 public final ObjectProperty<Effect> bumpInputProperty() { 191 if (bumpInput == null) { 192 bumpInput = new EffectInputProperty("bumpInput"); 193 } 194 return bumpInput; 195 } 196 197 /** 198 * The content input for this {@code Effect}. 199 * If set to {@code null}, or left unspecified, a graphical image of 200 * the {@code Node} to which the {@code Effect} is attached will be 201 * used as the input. 202 * @defaultValue null 203 */ 204 private ObjectProperty<Effect> contentInput; 205 206 207 public final void setContentInput(Effect value) { 208 contentInputProperty().set(value); 209 } 210 211 public final Effect getContentInput() { 212 return contentInput == null ? null : contentInput.get(); 213 } 214 215 public final ObjectProperty<Effect> contentInputProperty() { 216 if (contentInput == null) { 217 contentInput = new EffectInputProperty("contentInput"); 218 } 219 return contentInput; 220 } 221 222 @Override 223 boolean impl_checkChainContains(Effect e) { 224 Effect localBumpInput = getBumpInput(); 225 Effect localContentInput = getContentInput(); 226 if (localContentInput == e || localBumpInput == e) 227 return true; 228 if (localContentInput != null && localContentInput.impl_checkChainContains(e)) 229 return true; 230 if (localBumpInput != null && localBumpInput.impl_checkChainContains(e)) 231 return true; 232 233 return false; 234 } 235 236 /** 237 * The diffuse constant. 238 * <pre> 239 * Min: 0.0 240 * Max: 2.0 241 * Default: 1.0 242 * Identity: n/a 243 * </pre> 244 * @defaultValue 1.0 245 */ 246 private DoubleProperty diffuseConstant; 247 248 249 public final void setDiffuseConstant(double value) { 250 diffuseConstantProperty().set(value); 251 } 252 253 public final double getDiffuseConstant() { 254 return diffuseConstant == null ? 1 : diffuseConstant.get(); 255 } 256 257 public final DoubleProperty diffuseConstantProperty() { 258 if (diffuseConstant == null) { 259 diffuseConstant = new DoublePropertyBase(1) { 260 261 @Override 262 public void invalidated() { 263 markDirty(EffectDirtyBits.EFFECT_DIRTY); 264 } 265 266 @Override 267 public Object getBean() { 268 return Lighting.this; 269 } 270 271 @Override 272 public String getName() { 273 return "diffuseConstant"; 274 } 275 }; 276 } 277 return diffuseConstant; 278 } 279 280 /** 281 * The specular constant. 282 * <pre> 283 * Min: 0.0 284 * Max: 2.0 285 * Default: 0.3 286 * Identity: n/a 287 * </pre> 288 * @defaultValue 0.3 289 */ 290 private DoubleProperty specularConstant; 291 292 293 public final void setSpecularConstant(double value) { 294 specularConstantProperty().set(value); 295 } 296 297 public final double getSpecularConstant() { 298 return specularConstant == null ? 0.3 : specularConstant.get(); 299 } 300 301 public final DoubleProperty specularConstantProperty() { 302 if (specularConstant == null) { 303 specularConstant = new DoublePropertyBase(0.3) { 304 305 @Override 306 public void invalidated() { 307 markDirty(EffectDirtyBits.EFFECT_DIRTY); 308 } 309 310 @Override 311 public Object getBean() { 312 return Lighting.this; 313 } 314 315 @Override 316 public String getName() { 317 return "specularConstant"; 318 } 319 }; 320 } 321 return specularConstant; 322 } 323 324 /** 325 * The specular exponent. 326 * <pre> 327 * Min: 0.0 328 * Max: 40.0 329 * Default: 20.0 330 * Identity: n/a 331 * </pre> 332 * @defaultValue 20.0 333 */ 334 private DoubleProperty specularExponent; 335 336 337 public final void setSpecularExponent(double value) { 338 specularExponentProperty().set(value); 339 } 340 341 public final double getSpecularExponent() { 342 return specularExponent == null ? 20 : specularExponent.get(); 343 } 344 345 public final DoubleProperty specularExponentProperty() { 346 if (specularExponent == null) { 347 specularExponent = new DoublePropertyBase(20) { 348 349 @Override 350 public void invalidated() { 351 markDirty(EffectDirtyBits.EFFECT_DIRTY); 352 } 353 354 @Override 355 public Object getBean() { 356 return Lighting.this; 357 } 358 359 @Override 360 public String getName() { 361 return "specularExponent"; 362 } 363 }; 364 } 365 return specularExponent; 366 } 367 368 /** 369 * The surface scale factor. 370 * <pre> 371 * Min: 0.0 372 * Max: 10.0 373 * Default: 1.5 374 * Identity: n/a 375 * </pre> 376 * @defaultValue 1.5 377 */ 378 private DoubleProperty surfaceScale; 379 380 381 public final void setSurfaceScale(double value) { 382 surfaceScaleProperty().set(value); 383 } 384 385 public final double getSurfaceScale() { 386 return surfaceScale == null ? 1.5 : surfaceScale.get(); 387 } 388 389 public final DoubleProperty surfaceScaleProperty() { 390 if (surfaceScale == null) { 391 surfaceScale = new DoublePropertyBase(1.5) { 392 393 @Override 394 public void invalidated() { 395 markDirty(EffectDirtyBits.EFFECT_DIRTY); 396 } 397 398 @Override 399 public Object getBean() { 400 return Lighting.this; 401 } 402 403 @Override 404 public String getName() { 405 return "surfaceScale"; 406 } 407 }; 408 } 409 return surfaceScale; 410 } 411 412 private Light getLightInternal() { 413 Light localLight = getLight(); 414 return localLight == null ? defaultLight : localLight; 415 } 416 417 @Override 418 void impl_update() { 419 Effect localBumpInput = getBumpInput(); 420 421 if (localBumpInput != null) { 422 localBumpInput.impl_sync(); 423 } 424 425 Effect localContentInput = getContentInput(); 426 if (localContentInput != null) { 427 localContentInput.impl_sync(); 428 } 429 430 PhongLighting peer = (PhongLighting) impl_getImpl(); 431 peer.setBumpInput(localBumpInput == null ? null : localBumpInput.impl_getImpl()); 432 peer.setContentInput(localContentInput == null ? null : localContentInput.impl_getImpl()); 433 peer.setDiffuseConstant((float)Utils.clamp(0, getDiffuseConstant(), 2)); 434 peer.setSpecularConstant((float)Utils.clamp(0, getSpecularConstant(), 2)); 435 peer.setSpecularExponent((float)Utils.clamp(0, getSpecularExponent(), 40)); 436 peer.setSurfaceScale((float)Utils.clamp(0, getSurfaceScale(), 10)); 437 // we don't need to register on default light in case the light is null 438 // because default light never changes 439 lightChangeListener.register(getLight()); 440 441 getLightInternal().impl_sync(); 442 peer.setLight(getLightInternal().impl_getImpl()); 443 } 444 445 /** 446 * @treatAsPrivate implementation detail 447 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 448 */ 449 @Deprecated 450 @Override 451 public BaseBounds impl_getBounds(BaseBounds bounds, 452 BaseTransform tx, 453 Node node, 454 BoundsAccessor boundsAccessor) { 455 return EffectUtils.getInputBounds(bounds, tx, 456 node, boundsAccessor, 457 getContentInput()); 458 } 459}