1 /* 2 * HomeEnvironment.java 6 nov. 2008 3 * 4 * Sweet Home 3D, Copyright (c) 2008 Emmanuel PUYBARET / eTeks <info@eteks.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 package com.eteks.sweethome3d.model; 21 22 import java.beans.PropertyChangeEvent; 23 import java.beans.PropertyChangeListener; 24 import java.io.IOException; 25 import java.io.ObjectInputStream; 26 import java.io.Serializable; 27 import java.util.ArrayList; 28 import java.util.Collections; 29 import java.util.List; 30 31 /** 32 * The environment attributes of a home. 33 * @author Emmanuel Puybaret 34 */ 35 public class HomeEnvironment extends HomeObject implements Serializable, Cloneable { 36 private static final long serialVersionUID = 1L; 37 38 /** 39 * The environment properties that may change. 40 */ 41 public enum Property {OBSERVER_CAMERA_ELEVATION_ADJUSTED, GROUND_COLOR, GROUND_TEXTURE, BACKGROUND_IMAGE_VISIBLE_ON_GROUND_3D, 42 SKY_COLOR, SKY_TEXTURE, LIGHT_COLOR, CEILING_LIGHT_COLOR, 43 WALLS_ALPHA, DRAWING_MODE, SUBPART_SIZE_UNDER_LIGHT, ALL_LEVELS_VISIBLE, 44 PHOTO_WIDTH, PHOTO_HEIGHT, PHOTO_ASPECT_RATIO, PHOTO_QUALITY, 45 VIDEO_WIDTH, VIDEO_ASPECT_RATIO, VIDEO_QUALITY, VIDEO_SPEED, VIDEO_FRAME_RATE, VIDEO_CAMERA_PATH}; 46 /** 47 * The various modes used to draw home in 3D. 48 */ 49 public enum DrawingMode { 50 FILL, OUTLINE, FILL_AND_OUTLINE 51 } 52 53 private boolean observerCameraElevationAdjusted; 54 private int groundColor; 55 private HomeTexture groundTexture; 56 private boolean backgroundImageVisibleOnGround3D; 57 private int skyColor; 58 private HomeTexture skyTexture; 59 private int lightColor; 60 private int ceilingLightColor; 61 private float wallsAlpha; 62 private DrawingMode drawingMode; 63 private float subpartSizeUnderLight; 64 private boolean allLevelsVisible; 65 private int photoWidth; 66 private int photoHeight; 67 private transient AspectRatio photoAspectRatio; 68 // Aspect ratios are saved as a string to be able to keep backward compatibility 69 // if new constants are added to AspectRatio enum in future versions 70 private String photoAspectRatioName; 71 private int photoQuality; 72 private int videoWidth; 73 private transient AspectRatio videoAspectRatio; 74 // Aspect ratios are saved as a string to be able to keep backward compatibility 75 // if new constants are added to AspectRatio enum in future versions 76 private String videoAspectRatioName; 77 private int videoQuality; 78 private float videoSpeed; 79 private int videoFrameRate; 80 private List<Camera> cameraPath; 81 82 /** 83 * Creates default environment. 84 */ HomeEnvironment()85 public HomeEnvironment() { 86 this(HomeObject.createId("environment")); 87 } 88 89 /** 90 * Creates default environment. 91 * @since 6.4 92 */ HomeEnvironment(String id)93 public HomeEnvironment(String id) { 94 this(id, 95 0xA8A8A8, // Ground color 96 null, // Ground texture 97 0xCCE4FC, // Sky color 98 null, // Sky texture 99 0xD0D0D0, // Light color 100 0); // Walls alpha 101 } 102 103 /** 104 * Creates home environment from parameters. 105 */ HomeEnvironment(int groundColor, HomeTexture groundTexture, int skyColor, int lightColor, float wallsAlpha)106 public HomeEnvironment(int groundColor, 107 HomeTexture groundTexture, int skyColor, 108 int lightColor, float wallsAlpha) { 109 this(groundColor, groundTexture, skyColor, null, 110 lightColor, wallsAlpha); 111 } 112 113 /** 114 * Creates home environment from parameters. 115 * @since 2.2 116 */ HomeEnvironment(int groundColor, HomeTexture groundTexture, int skyColor, HomeTexture skyTexture, int lightColor, float wallsAlpha)117 public HomeEnvironment(int groundColor, HomeTexture groundTexture, 118 int skyColor, HomeTexture skyTexture, 119 int lightColor, float wallsAlpha) { 120 this(HomeObject.createId("environment"), groundColor, groundTexture, 121 skyColor, skyTexture, lightColor, wallsAlpha); 122 } 123 124 /** 125 * Creates home environment from parameters. 126 * @since 6.4 127 */ HomeEnvironment(String id, int groundColor, HomeTexture groundTexture, int skyColor, HomeTexture skyTexture, int lightColor, float wallsAlpha)128 public HomeEnvironment(String id, 129 int groundColor, HomeTexture groundTexture, 130 int skyColor, HomeTexture skyTexture, 131 int lightColor, float wallsAlpha) { 132 super(id); 133 this.observerCameraElevationAdjusted = true; 134 this.groundColor = groundColor; 135 this.groundTexture = groundTexture; 136 this.skyColor = skyColor; 137 this.skyTexture = skyTexture; 138 this.lightColor = lightColor; 139 this.ceilingLightColor = 0xD0D0D0; 140 this.wallsAlpha = wallsAlpha; 141 this.drawingMode = DrawingMode.FILL; 142 this.photoWidth = 400; 143 this.photoHeight = 300; 144 this.photoAspectRatio = AspectRatio.VIEW_3D_RATIO; 145 this.videoWidth = 320; 146 this.videoAspectRatio = AspectRatio.RATIO_4_3; 147 this.videoSpeed = 2400f / 3600; // 2.4 km/h 148 this.videoFrameRate = 25; 149 this.cameraPath = Collections.emptyList(); 150 } 151 152 /** 153 * Initializes environment transient fields 154 * and reads attributes from <code>in</code> stream with default reading method. 155 */ readObject(ObjectInputStream in)156 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 157 this.ceilingLightColor = 0xD0D0D0; 158 this.photoWidth = 400; 159 this.photoHeight = 300; 160 this.photoAspectRatio = AspectRatio.VIEW_3D_RATIO; 161 this.videoWidth = 320; 162 this.videoAspectRatio = AspectRatio.RATIO_4_3; 163 this.videoSpeed = 2400f / 3600; 164 this.videoFrameRate = 25; 165 this.cameraPath = Collections.emptyList(); 166 in.defaultReadObject(); 167 try { 168 // Read aspect from a string 169 if (this.photoAspectRatioName != null) { 170 this.photoAspectRatio = AspectRatio.valueOf(this.photoAspectRatioName); 171 } 172 } catch (IllegalArgumentException ex) { 173 // Ignore malformed enum constant 174 } 175 try { 176 // Read aspect from a string 177 if (this.videoAspectRatioName != null) { 178 this.videoAspectRatio = AspectRatio.valueOf(this.videoAspectRatioName); 179 } 180 } catch (IllegalArgumentException ex) { 181 // Ignore malformed enum constant 182 } 183 } 184 185 /** 186 * Adds the property change <code>listener</code> in parameter to this environment. 187 * Properties change will be notified with an event of {@link PropertyChangeEvent} class which property name 188 * will be equal to the value returned by {@link Property#name()} call. 189 */ addPropertyChangeListener(Property property, PropertyChangeListener listener)190 public void addPropertyChangeListener(Property property, PropertyChangeListener listener) { 191 addPropertyChangeListener(property.name(), listener); 192 } 193 194 /** 195 * Removes the property change <code>listener</code> in parameter from this environment. 196 */ removePropertyChangeListener(Property property, PropertyChangeListener listener)197 public void removePropertyChangeListener(Property property, PropertyChangeListener listener) { 198 removePropertyChangeListener(property.name(), listener); 199 } 200 201 /** 202 * Returns <code>true</code> if the observer elevation should be adjusted according 203 * to the elevation of the selected level. 204 * @since 3.5 205 */ isObserverCameraElevationAdjusted()206 public boolean isObserverCameraElevationAdjusted() { 207 return this.observerCameraElevationAdjusted; 208 } 209 210 /** 211 * Sets whether the observer elevation should be adjusted according 212 * to the elevation of the selected level and fires a <code>PropertyChangeEvent</code>. 213 * @since 3.5 214 */ setObserverCameraElevationAdjusted(boolean observerCameraElevationAdjusted)215 public void setObserverCameraElevationAdjusted(boolean observerCameraElevationAdjusted) { 216 if (this.observerCameraElevationAdjusted != observerCameraElevationAdjusted) { 217 this.observerCameraElevationAdjusted = observerCameraElevationAdjusted; 218 firePropertyChange(Property.OBSERVER_CAMERA_ELEVATION_ADJUSTED.name(), 219 !observerCameraElevationAdjusted, observerCameraElevationAdjusted); 220 } 221 } 222 223 /** 224 * Returns the ground color of this environment. 225 */ getGroundColor()226 public int getGroundColor() { 227 return this.groundColor; 228 } 229 230 /** 231 * Sets the ground color of this environment and fires a <code>PropertyChangeEvent</code>. 232 */ setGroundColor(int groundColor)233 public void setGroundColor(int groundColor) { 234 if (groundColor != this.groundColor) { 235 int oldGroundColor = this.groundColor; 236 this.groundColor = groundColor; 237 firePropertyChange(Property.GROUND_COLOR.name(), oldGroundColor, groundColor); 238 } 239 } 240 241 /** 242 * Returns the ground texture of this environment. 243 */ getGroundTexture()244 public HomeTexture getGroundTexture() { 245 return this.groundTexture; 246 } 247 248 /** 249 * Sets the ground texture of this environment and fires a <code>PropertyChangeEvent</code>. 250 */ setGroundTexture(HomeTexture groundTexture)251 public void setGroundTexture(HomeTexture groundTexture) { 252 if (groundTexture != this.groundTexture) { 253 HomeTexture oldGroundTexture = this.groundTexture; 254 this.groundTexture = groundTexture; 255 firePropertyChange(Property.GROUND_TEXTURE.name(), oldGroundTexture, groundTexture); 256 } 257 } 258 259 /** 260 * Returns <code>true</code> if the background image should be displayed on the ground in 3D. 261 * @since 6.0 262 */ isBackgroundImageVisibleOnGround3D()263 public boolean isBackgroundImageVisibleOnGround3D() { 264 return this.backgroundImageVisibleOnGround3D; 265 } 266 267 /** 268 * Sets whether the background image should be displayed on the ground in 3D and 269 * fires a <code>PropertyChangeEvent</code>. 270 * @since 6.0 271 */ setBackgroundImageVisibleOnGround3D(boolean backgroundImageVisibleOnGround3D)272 public void setBackgroundImageVisibleOnGround3D(boolean backgroundImageVisibleOnGround3D) { 273 if (this.backgroundImageVisibleOnGround3D != backgroundImageVisibleOnGround3D) { 274 this.backgroundImageVisibleOnGround3D = backgroundImageVisibleOnGround3D; 275 firePropertyChange(Property.BACKGROUND_IMAGE_VISIBLE_ON_GROUND_3D.name(), 276 !backgroundImageVisibleOnGround3D, backgroundImageVisibleOnGround3D); 277 } 278 } 279 280 /** 281 * Returns the sky color of this environment. 282 */ getSkyColor()283 public int getSkyColor() { 284 return this.skyColor; 285 } 286 287 /** 288 * Sets the sky color of this environment and fires a <code>PropertyChangeEvent</code>. 289 */ setSkyColor(int skyColor)290 public void setSkyColor(int skyColor) { 291 if (skyColor != this.skyColor) { 292 int oldSkyColor = this.skyColor; 293 this.skyColor = skyColor; 294 firePropertyChange(Property.SKY_COLOR.name(), oldSkyColor, skyColor); 295 } 296 } 297 298 /** 299 * Returns the sky texture of this environment. 300 */ getSkyTexture()301 public HomeTexture getSkyTexture() { 302 return this.skyTexture; 303 } 304 305 /** 306 * Sets the sky texture of this environment and fires a <code>PropertyChangeEvent</code>. 307 */ setSkyTexture(HomeTexture skyTexture)308 public void setSkyTexture(HomeTexture skyTexture) { 309 if (skyTexture != this.skyTexture) { 310 HomeTexture oldSkyTexture = this.skyTexture; 311 this.skyTexture = skyTexture; 312 firePropertyChange(Property.SKY_TEXTURE.name(), oldSkyTexture, skyTexture); 313 } 314 } 315 316 /** 317 * Returns the light color of this environment. 318 */ getLightColor()319 public int getLightColor() { 320 return this.lightColor; 321 } 322 323 /** 324 * Sets the color that lights this environment and fires a <code>PropertyChangeEvent</code>. 325 */ setLightColor(int lightColor)326 public void setLightColor(int lightColor) { 327 if (lightColor != this.lightColor) { 328 int oldLightColor = this.lightColor; 329 this.lightColor = lightColor; 330 firePropertyChange(Property.LIGHT_COLOR.name(), oldLightColor, lightColor); 331 } 332 } 333 334 /** 335 * Returns the color of ceiling lights. 336 */ getCeillingLightColor()337 public int getCeillingLightColor() { 338 return this.ceilingLightColor; 339 } 340 341 /** 342 * Sets the color of ceiling lights and fires a <code>PropertyChangeEvent</code>. 343 */ setCeillingLightColor(int ceilingLightColor)344 public void setCeillingLightColor(int ceilingLightColor) { 345 if (ceilingLightColor != this.ceilingLightColor) { 346 int oldCeilingLightColor = this.ceilingLightColor; 347 this.ceilingLightColor = ceilingLightColor; 348 firePropertyChange(Property.CEILING_LIGHT_COLOR.name(), oldCeilingLightColor, ceilingLightColor); 349 } 350 } 351 352 /** 353 * Returns the walls transparency alpha factor of this environment. 354 */ getWallsAlpha()355 public float getWallsAlpha() { 356 return this.wallsAlpha; 357 } 358 359 /** 360 * Sets the walls transparency alpha of this environment and fires a <code>PropertyChangeEvent</code>. 361 * @param wallsAlpha a value between 0 and 1, 0 meaning opaque and 1 invisible. 362 */ setWallsAlpha(float wallsAlpha)363 public void setWallsAlpha(float wallsAlpha) { 364 if (wallsAlpha != this.wallsAlpha) { 365 float oldWallsAlpha = this.wallsAlpha; 366 this.wallsAlpha = wallsAlpha; 367 firePropertyChange(Property.WALLS_ALPHA.name(), oldWallsAlpha, wallsAlpha); 368 } 369 } 370 371 /** 372 * Returns the drawing mode of this environment. 373 */ getDrawingMode()374 public DrawingMode getDrawingMode() { 375 return this.drawingMode; 376 } 377 378 /** 379 * Sets the drawing mode of this environment and fires a <code>PropertyChangeEvent</code>. 380 */ setDrawingMode(DrawingMode drawingMode)381 public void setDrawingMode(DrawingMode drawingMode) { 382 if (drawingMode != this.drawingMode) { 383 DrawingMode oldDrawingMode = this.drawingMode; 384 this.drawingMode = drawingMode; 385 firePropertyChange(Property.DRAWING_MODE.name(), oldDrawingMode, drawingMode); 386 } 387 } 388 389 /** 390 * Returns the size of subparts under home lights in this environment. 391 * @return a size in centimeters or 0 if home lights don't illuminate home. 392 * @since 3.7 393 */ getSubpartSizeUnderLight()394 public float getSubpartSizeUnderLight() { 395 return this.subpartSizeUnderLight; 396 } 397 398 /** 399 * Sets the size of subparts under home lights of this environment and fires a <code>PropertyChangeEvent</code>. 400 * @since 3.7 401 */ setSubpartSizeUnderLight(float subpartSizeUnderLight)402 public void setSubpartSizeUnderLight(float subpartSizeUnderLight) { 403 if (subpartSizeUnderLight != this.subpartSizeUnderLight) { 404 float oldSubpartWidthUnderLight = this.subpartSizeUnderLight; 405 this.subpartSizeUnderLight = subpartSizeUnderLight; 406 firePropertyChange(Property.SUBPART_SIZE_UNDER_LIGHT.name(), oldSubpartWidthUnderLight, subpartSizeUnderLight); 407 } 408 } 409 410 /** 411 * Returns whether all levels should be visible or not. 412 */ isAllLevelsVisible()413 public boolean isAllLevelsVisible() { 414 return this.allLevelsVisible; 415 } 416 417 /** 418 * Sets whether all levels should be visible or not and fires a <code>PropertyChangeEvent</code>. 419 */ setAllLevelsVisible(boolean allLevelsVisible)420 public void setAllLevelsVisible(boolean allLevelsVisible) { 421 if (allLevelsVisible != this.allLevelsVisible) { 422 this.allLevelsVisible = allLevelsVisible; 423 firePropertyChange(Property.ALL_LEVELS_VISIBLE.name(), !allLevelsVisible, allLevelsVisible); 424 } 425 } 426 427 /** 428 * Returns the preferred photo width. 429 * @since 2.0 430 */ getPhotoWidth()431 public int getPhotoWidth() { 432 return this.photoWidth; 433 } 434 435 /** 436 * Sets the preferred photo width, and notifies 437 * listeners of this change. 438 * @since 2.0 439 */ setPhotoWidth(int photoWidth)440 public void setPhotoWidth(int photoWidth) { 441 if (this.photoWidth != photoWidth) { 442 int oldPhotoWidth = this.photoWidth; 443 this.photoWidth = photoWidth; 444 firePropertyChange(Property.PHOTO_WIDTH.name(), oldPhotoWidth, photoWidth); 445 } 446 } 447 448 /** 449 * Returns the preferred photo height. 450 * @since 2.0 451 */ getPhotoHeight()452 public int getPhotoHeight() { 453 return this.photoHeight; 454 } 455 456 /** 457 * Sets the preferred photo height, and notifies 458 * listeners of this change. 459 * @since 2.0 460 */ setPhotoHeight(int photoHeight)461 public void setPhotoHeight(int photoHeight) { 462 if (this.photoHeight != photoHeight) { 463 int oldPhotoHeight = this.photoHeight; 464 this.photoHeight = photoHeight; 465 firePropertyChange(Property.PHOTO_HEIGHT.name(), oldPhotoHeight, photoHeight); 466 } 467 } 468 469 /** 470 * Returns the preferred photo aspect ratio. 471 * @since 2.0 472 */ getPhotoAspectRatio()473 public AspectRatio getPhotoAspectRatio() { 474 return this.photoAspectRatio; 475 } 476 477 /** 478 * Sets the preferred photo aspect ratio, and notifies 479 * listeners of this change. 480 * @since 2.0 481 */ setPhotoAspectRatio(AspectRatio photoAspectRatio)482 public void setPhotoAspectRatio(AspectRatio photoAspectRatio) { 483 if (this.photoAspectRatio != photoAspectRatio) { 484 AspectRatio oldPhotoAspectRatio = this.photoAspectRatio; 485 this.photoAspectRatio = photoAspectRatio; 486 this.photoAspectRatioName = this.photoAspectRatio.name(); 487 firePropertyChange(Property.PHOTO_ASPECT_RATIO.name(), oldPhotoAspectRatio, photoAspectRatio); 488 } 489 } 490 491 /** 492 * Returns the preferred photo quality. 493 * @since 2.0 494 */ getPhotoQuality()495 public int getPhotoQuality() { 496 return this.photoQuality; 497 } 498 499 /** 500 * Sets preferred photo quality, and notifies 501 * listeners of this change. 502 * @since 2.0 503 */ setPhotoQuality(int photoQuality)504 public void setPhotoQuality(int photoQuality) { 505 if (this.photoQuality != photoQuality) { 506 int oldPhotoQuality = this.photoQuality; 507 this.photoQuality = photoQuality; 508 firePropertyChange(Property.PHOTO_QUALITY.name(), oldPhotoQuality, photoQuality); 509 } 510 } 511 512 /** 513 * Returns the preferred video width. 514 * @since 2.3 515 */ getVideoWidth()516 public int getVideoWidth() { 517 return this.videoWidth; 518 } 519 520 /** 521 * Sets the preferred video width, and notifies 522 * listeners of this change. 523 * @since 2.3 524 */ setVideoWidth(int videoWidth)525 public void setVideoWidth(int videoWidth) { 526 if (this.videoWidth != videoWidth) { 527 int oldVideoWidth = this.videoWidth; 528 this.videoWidth = videoWidth; 529 firePropertyChange(Property.VIDEO_WIDTH.name(), oldVideoWidth, videoWidth); 530 } 531 } 532 533 /** 534 * Returns the preferred video height. 535 * @since 2.3 536 */ getVideoHeight()537 public int getVideoHeight() { 538 return Math.round(getVideoWidth() / getVideoAspectRatio().getValue()); 539 } 540 541 /** 542 * Returns the preferred video aspect ratio. 543 * @since 2.3 544 */ getVideoAspectRatio()545 public AspectRatio getVideoAspectRatio() { 546 return this.videoAspectRatio; 547 } 548 549 /** 550 * Sets the preferred video aspect ratio, and notifies 551 * listeners of this change. 552 * @since 2.3 553 */ setVideoAspectRatio(AspectRatio videoAspectRatio)554 public void setVideoAspectRatio(AspectRatio videoAspectRatio) { 555 if (this.videoAspectRatio != videoAspectRatio) { 556 if (videoAspectRatio.getValue() == null) { 557 throw new IllegalArgumentException("Unsupported aspect ratio " + videoAspectRatio); 558 } 559 AspectRatio oldVideoAspectRatio = this.videoAspectRatio; 560 this.videoAspectRatio = videoAspectRatio; 561 this.videoAspectRatioName = this.videoAspectRatio.name(); 562 firePropertyChange(Property.VIDEO_ASPECT_RATIO.name(), oldVideoAspectRatio, videoAspectRatio); 563 } 564 } 565 566 /** 567 * Returns preferred video quality. 568 * @since 2.3 569 */ getVideoQuality()570 public int getVideoQuality() { 571 return this.videoQuality; 572 } 573 574 /** 575 * Sets the preferred video quality, and notifies 576 * listeners of this change. 577 * @since 2.3 578 */ setVideoQuality(int videoQuality)579 public void setVideoQuality(int videoQuality) { 580 if (this.videoQuality != videoQuality) { 581 int oldVideoQuality = this.videoQuality; 582 this.videoQuality = videoQuality; 583 firePropertyChange(Property.VIDEO_QUALITY.name(), oldVideoQuality, videoQuality); 584 } 585 } 586 587 /** 588 * Returns the preferred speed of movements in videos in m/s. 589 * @since 6.0 590 */ getVideoSpeed()591 public float getVideoSpeed() { 592 return this.videoSpeed; 593 } 594 595 /** 596 * Sets the preferred speed of movements in videos in m/s. 597 * @since 6.0 598 */ setVideoSpeed(float videoSpeed)599 public void setVideoSpeed(float videoSpeed) { 600 if (this.videoSpeed != videoSpeed) { 601 float oldVideoSpeed = this.videoSpeed; 602 this.videoSpeed = videoSpeed; 603 firePropertyChange(Property.VIDEO_SPEED.name(), oldVideoSpeed, videoSpeed); 604 } 605 } 606 607 /** 608 * Returns the preferred video frame rate. 609 * @since 2.3 610 */ getVideoFrameRate()611 public int getVideoFrameRate() { 612 return this.videoFrameRate; 613 } 614 615 /** 616 * Sets the preferred video frame rate, and notifies 617 * listeners of this change. 618 * @since 2.3 619 */ setVideoFrameRate(int videoFrameRate)620 public void setVideoFrameRate(int videoFrameRate) { 621 if (this.videoFrameRate != videoFrameRate) { 622 int oldVideoFrameRate = this.videoFrameRate; 623 this.videoFrameRate = videoFrameRate; 624 firePropertyChange(Property.VIDEO_FRAME_RATE.name(), oldVideoFrameRate, videoFrameRate); 625 } 626 } 627 628 /** 629 * Returns the preferred video camera path. 630 * @since 2.3 631 */ getVideoCameraPath()632 public List<Camera> getVideoCameraPath() { 633 return Collections.unmodifiableList(this.cameraPath); 634 } 635 636 /** 637 * Sets the preferred video camera path, and notifies 638 * listeners of this change. 639 * @since 2.3 640 */ setVideoCameraPath(List<Camera> cameraPath)641 public void setVideoCameraPath(List<Camera> cameraPath) { 642 if (this.cameraPath != cameraPath) { 643 List<Camera> oldCameraPath = this.cameraPath; 644 if (cameraPath != null) { 645 this.cameraPath = new ArrayList<Camera>(cameraPath); 646 } else { 647 this.cameraPath = Collections.emptyList(); 648 } 649 firePropertyChange(Property.VIDEO_CAMERA_PATH.name(), oldCameraPath, cameraPath); 650 } 651 } 652 653 /** 654 * Returns a clone of this environment. 655 * @since 2.3 656 */ 657 @Override clone()658 public HomeEnvironment clone() { 659 HomeEnvironment clone = (HomeEnvironment)super.clone(); 660 clone.cameraPath = new ArrayList<Camera>(this.cameraPath.size()); 661 for (Camera camera : this.cameraPath) { 662 clone.cameraPath.add(camera.clone()); 663 } 664 return clone; 665 } 666 }