136 import com.sun.javafx.geom.RectBounds;
137 import com.sun.javafx.geom.Vec3d;
138 import com.sun.javafx.geom.transform.Affine3D;
139 import com.sun.javafx.geom.transform.BaseTransform;
140 import com.sun.javafx.geom.transform.GeneralTransform3D;
141 import com.sun.javafx.geom.transform.NoninvertibleTransformException;
142 import com.sun.javafx.jmx.MXNodeAlgorithm;
143 import com.sun.javafx.jmx.MXNodeAlgorithmContext;
144 import com.sun.javafx.perf.PerformanceTracker;
145 import com.sun.javafx.scene.BoundsAccessor;
146 import com.sun.javafx.scene.CameraHelper;
147 import com.sun.javafx.scene.CssFlags;
148 import com.sun.javafx.scene.DirtyBits;
149 import com.sun.javafx.scene.EventHandlerProperties;
150 import com.sun.javafx.scene.LayoutFlags;
151 import com.sun.javafx.scene.NodeEventDispatcher;
152 import com.sun.javafx.scene.NodeHelper;
153 import com.sun.javafx.scene.SceneHelper;
154 import com.sun.javafx.scene.SceneUtils;
155 import com.sun.javafx.scene.input.PickResultChooser;
156 import com.sun.javafx.scene.transform.TransformUtils;
157 import com.sun.javafx.scene.traversal.Direction;
158 import com.sun.javafx.sg.prism.NGNode;
159 import com.sun.javafx.tk.Toolkit;
160 import com.sun.prism.impl.PrismSettings;
161 import com.sun.scenario.effect.EffectHelper;
162
163 import javafx.scene.shape.Shape3D;
164 import sun.util.logging.PlatformLogger;
165 import sun.util.logging.PlatformLogger.Level;
166
167 /**
168 * Base class for scene graph nodes. A scene graph is a set of tree data structures
169 * where every item has zero or one parent, and each item is either
170 * a "leaf" with zero sub-items or a "branch" with zero or more sub-items.
171 * <p>
172 * Each item in the scene graph is called a {@code Node}. Branch nodes are
173 * of type {@link Parent}, whose concrete subclasses are {@link Group},
174 * {@link javafx.scene.layout.Region}, and {@link javafx.scene.control.Control},
175 * or subclasses thereof.
1848
1849 private void doCSSLayoutSyncForSnapshot() {
1850 doCSSPass();
1851 doLayoutPass();
1852 updateBounds();
1853 Scene.impl_setAllowPGAccess(true);
1854 syncAll(this);
1855 Scene.impl_setAllowPGAccess(false);
1856 }
1857
1858 private WritableImage doSnapshot(SnapshotParameters params, WritableImage img) {
1859 if (getScene() != null) {
1860 getScene().doCSSLayoutSyncForSnapshot(this);
1861 } else {
1862 doCSSLayoutSyncForSnapshot();
1863 }
1864
1865 BaseTransform transform = BaseTransform.IDENTITY_TRANSFORM;
1866 if (params.getTransform() != null) {
1867 Affine3D tempTx = new Affine3D();
1868 params.getTransform().impl_apply(tempTx);
1869 transform = tempTx;
1870 }
1871 double x;
1872 double y;
1873 double w;
1874 double h;
1875 Rectangle2D viewport = params.getViewport();
1876 if (viewport != null) {
1877 // Use the specified viewport
1878 x = viewport.getMinX();
1879 y = viewport.getMinY();
1880 w = viewport.getWidth();
1881 h = viewport.getHeight();
1882 } else {
1883 // Get the bounds in parent of this node, transformed by the
1884 // specified transform.
1885 BaseBounds tempBounds = TempState.getInstance().bounds;
1886 tempBounds = getTransformedBounds(tempBounds, transform);
1887 x = tempBounds.getMinX();
1888 y = tempBounds.getMinY();
3076 minZ = tempV3D.z;
3077
3078 tempV3D.set(0, 0, bounds.getMaxZ());
3079 localToScene(tempV3D);
3080 maxZ = tempV3D.z;
3081 } else {
3082 Bounds nodeInSceneBounds = localToScene(bounds);
3083 minZ = nodeInSceneBounds.getMinZ();
3084 maxZ = nodeInSceneBounds.getMaxZ();
3085 }
3086
3087 if (minZ > camera.getFarClipInScene()
3088 || maxZ < camera.getNearClipInScene()) {
3089 return 0;
3090 }
3091
3092 } else {
3093 BaseBounds nodeInCameraBounds = new BoxBounds();
3094
3095 // We need to set tempTx to identity since it is a recycled transform.
3096 // This is because impl_apply is a matrix concatenation operation.
3097 tempTx.setToIdentity();
3098 localToSceneTx.impl_apply(tempTx);
3099
3100 // Convert node from local coordinate to camera coordinate
3101 tempTx.preConcatenate(camera.getSceneToLocalTransform());
3102 tempTx.transform(localBounds, nodeInCameraBounds);
3103
3104 // Compare in camera coornidate
3105 if (nodeInCameraBounds.getMinZ() > camera.getFarClip()
3106 || nodeInCameraBounds.getMaxZ() < camera.getNearClip()) {
3107 return 0;
3108 }
3109 }
3110 }
3111
3112 GeneralTransform3D projViewTx = TempState.getInstance().projViewTx;
3113 projViewTx.set(camera.getProjViewTransform());
3114
3115 // We need to set tempTx to identity since it is a recycled transform.
3116 // This is because impl_apply is a matrix concatenation operation.
3117 tempTx.setToIdentity();
3118 localToSceneTx.impl_apply(tempTx);
3119
3120 // The product of projViewTx * localToSceneTransform
3121 GeneralTransform3D tx = projViewTx.mul(tempTx);
3122
3123 // Transform localBounds to projected bounds
3124 localBounds = tx.transform(localBounds, localBounds);
3125 double area = localBounds.getWidth() * localBounds.getHeight();
3126
3127 // Use canonical view volume to check whether object is outside the
3128 // viewing frustrum
3129 if (isPerspective) {
3130 localBounds.intersectWith(-1, -1, 0, 1, 1, 1);
3131 area = (localBounds.getWidth() < 0 || localBounds.getHeight() < 0) ? 0 : area;
3132 }
3133 return area * (camera.getViewWidth() / 2 * camera.getViewHeight() / 2);
3134 }
3135 return 0;
3136 }
3137
3138 /* *************************************************************************
4805 localToParentTx = localToParentTx.deriveWithTranslation(
4806 getTranslateX() + getLayoutX() + pivotX,
4807 getTranslateY() + getLayoutY() + pivotY,
4808 getTranslateZ() + pivotZ);
4809 localToParentTx = localToParentTx.deriveWithRotation(
4810 Math.toRadians(getRotate()), getRotationAxis().getX(),
4811 getRotationAxis().getY(), getRotationAxis().getZ());
4812 localToParentTx = localToParentTx.deriveWithScale(
4813 getScaleX(), getScaleY(), getScaleZ());
4814 localToParentTx = localToParentTx.deriveWithTranslation(
4815 -pivotX, -pivotY, -pivotZ);
4816 } else {
4817 localToParentTx = localToParentTx.deriveWithTranslation(
4818 getTranslateX() + getLayoutX(),
4819 getTranslateY() + getLayoutY(),
4820 getTranslateZ());
4821 }
4822
4823 if (impl_hasTransforms()) {
4824 for (Transform t : getTransforms()) {
4825 localToParentTx = t.impl_derive(localToParentTx);
4826 }
4827 }
4828
4829 // Check to see whether the node requires mirroring
4830 if (mirror) {
4831 localToParentTx = localToParentTx.deriveWithTranslation(
4832 mirroringCenter, 0);
4833 localToParentTx = localToParentTx.deriveWithScale(
4834 -1.0, 1.0, 1.0);
4835 localToParentTx = localToParentTx.deriveWithTranslation(
4836 -mirroringCenter, 0);
4837 }
4838
4839 transformDirty = false;
4840 }
4841 }
4842
4843 /**
4844 * Transforms in place the specified point from parent coords to local
4845 * coords. Made package private for the sake of testing.
6074 public Object getBean() {
6075 return Node.this;
6076 }
6077
6078 @Override
6079 public String getName() {
6080 return "rotationAxis";
6081 }
6082 };
6083 }
6084 return rotationAxis;
6085 }
6086
6087 public ObservableList<Transform> getTransforms() {
6088 if (transforms == null) {
6089 transforms = new TrackableObservableList<Transform>() {
6090 @Override
6091 protected void onChanged(Change<Transform> c) {
6092 while (c.next()) {
6093 for (Transform t : c.getRemoved()) {
6094 t.impl_remove(Node.this);
6095 }
6096 for (Transform t : c.getAddedSubList()) {
6097 t.impl_add(Node.this);
6098 }
6099 }
6100
6101 impl_transformsChanged();
6102 }
6103 };
6104 }
6105
6106 return transforms;
6107 }
6108
6109 public boolean canSetTranslateX() {
6110 return (translateX == null) || !translateX.isBound();
6111 }
6112
6113 public boolean canSetTranslateY() {
6114 return (translateY == null) || !translateY.isBound();
6115 }
6116
6117 public boolean canSetTranslateZ() {
|
136 import com.sun.javafx.geom.RectBounds;
137 import com.sun.javafx.geom.Vec3d;
138 import com.sun.javafx.geom.transform.Affine3D;
139 import com.sun.javafx.geom.transform.BaseTransform;
140 import com.sun.javafx.geom.transform.GeneralTransform3D;
141 import com.sun.javafx.geom.transform.NoninvertibleTransformException;
142 import com.sun.javafx.jmx.MXNodeAlgorithm;
143 import com.sun.javafx.jmx.MXNodeAlgorithmContext;
144 import com.sun.javafx.perf.PerformanceTracker;
145 import com.sun.javafx.scene.BoundsAccessor;
146 import com.sun.javafx.scene.CameraHelper;
147 import com.sun.javafx.scene.CssFlags;
148 import com.sun.javafx.scene.DirtyBits;
149 import com.sun.javafx.scene.EventHandlerProperties;
150 import com.sun.javafx.scene.LayoutFlags;
151 import com.sun.javafx.scene.NodeEventDispatcher;
152 import com.sun.javafx.scene.NodeHelper;
153 import com.sun.javafx.scene.SceneHelper;
154 import com.sun.javafx.scene.SceneUtils;
155 import com.sun.javafx.scene.input.PickResultChooser;
156 import com.sun.javafx.scene.transform.TransformHelper;
157 import com.sun.javafx.scene.transform.TransformUtils;
158 import com.sun.javafx.scene.traversal.Direction;
159 import com.sun.javafx.sg.prism.NGNode;
160 import com.sun.javafx.tk.Toolkit;
161 import com.sun.prism.impl.PrismSettings;
162 import com.sun.scenario.effect.EffectHelper;
163
164 import javafx.scene.shape.Shape3D;
165 import sun.util.logging.PlatformLogger;
166 import sun.util.logging.PlatformLogger.Level;
167
168 /**
169 * Base class for scene graph nodes. A scene graph is a set of tree data structures
170 * where every item has zero or one parent, and each item is either
171 * a "leaf" with zero sub-items or a "branch" with zero or more sub-items.
172 * <p>
173 * Each item in the scene graph is called a {@code Node}. Branch nodes are
174 * of type {@link Parent}, whose concrete subclasses are {@link Group},
175 * {@link javafx.scene.layout.Region}, and {@link javafx.scene.control.Control},
176 * or subclasses thereof.
1849
1850 private void doCSSLayoutSyncForSnapshot() {
1851 doCSSPass();
1852 doLayoutPass();
1853 updateBounds();
1854 Scene.impl_setAllowPGAccess(true);
1855 syncAll(this);
1856 Scene.impl_setAllowPGAccess(false);
1857 }
1858
1859 private WritableImage doSnapshot(SnapshotParameters params, WritableImage img) {
1860 if (getScene() != null) {
1861 getScene().doCSSLayoutSyncForSnapshot(this);
1862 } else {
1863 doCSSLayoutSyncForSnapshot();
1864 }
1865
1866 BaseTransform transform = BaseTransform.IDENTITY_TRANSFORM;
1867 if (params.getTransform() != null) {
1868 Affine3D tempTx = new Affine3D();
1869 TransformHelper.apply(params.getTransform(), tempTx);
1870 transform = tempTx;
1871 }
1872 double x;
1873 double y;
1874 double w;
1875 double h;
1876 Rectangle2D viewport = params.getViewport();
1877 if (viewport != null) {
1878 // Use the specified viewport
1879 x = viewport.getMinX();
1880 y = viewport.getMinY();
1881 w = viewport.getWidth();
1882 h = viewport.getHeight();
1883 } else {
1884 // Get the bounds in parent of this node, transformed by the
1885 // specified transform.
1886 BaseBounds tempBounds = TempState.getInstance().bounds;
1887 tempBounds = getTransformedBounds(tempBounds, transform);
1888 x = tempBounds.getMinX();
1889 y = tempBounds.getMinY();
3077 minZ = tempV3D.z;
3078
3079 tempV3D.set(0, 0, bounds.getMaxZ());
3080 localToScene(tempV3D);
3081 maxZ = tempV3D.z;
3082 } else {
3083 Bounds nodeInSceneBounds = localToScene(bounds);
3084 minZ = nodeInSceneBounds.getMinZ();
3085 maxZ = nodeInSceneBounds.getMaxZ();
3086 }
3087
3088 if (minZ > camera.getFarClipInScene()
3089 || maxZ < camera.getNearClipInScene()) {
3090 return 0;
3091 }
3092
3093 } else {
3094 BaseBounds nodeInCameraBounds = new BoxBounds();
3095
3096 // We need to set tempTx to identity since it is a recycled transform.
3097 // This is because TransformHelper.apply() is a matrix concatenation operation.
3098 tempTx.setToIdentity();
3099 TransformHelper.apply(localToSceneTx, tempTx);
3100
3101 // Convert node from local coordinate to camera coordinate
3102 tempTx.preConcatenate(camera.getSceneToLocalTransform());
3103 tempTx.transform(localBounds, nodeInCameraBounds);
3104
3105 // Compare in camera coornidate
3106 if (nodeInCameraBounds.getMinZ() > camera.getFarClip()
3107 || nodeInCameraBounds.getMaxZ() < camera.getNearClip()) {
3108 return 0;
3109 }
3110 }
3111 }
3112
3113 GeneralTransform3D projViewTx = TempState.getInstance().projViewTx;
3114 projViewTx.set(camera.getProjViewTransform());
3115
3116 // We need to set tempTx to identity since it is a recycled transform.
3117 // This is because TransformHelper.apply() is a matrix concatenation operation.
3118 tempTx.setToIdentity();
3119 TransformHelper.apply(localToSceneTx, tempTx);
3120
3121 // The product of projViewTx * localToSceneTransform
3122 GeneralTransform3D tx = projViewTx.mul(tempTx);
3123
3124 // Transform localBounds to projected bounds
3125 localBounds = tx.transform(localBounds, localBounds);
3126 double area = localBounds.getWidth() * localBounds.getHeight();
3127
3128 // Use canonical view volume to check whether object is outside the
3129 // viewing frustrum
3130 if (isPerspective) {
3131 localBounds.intersectWith(-1, -1, 0, 1, 1, 1);
3132 area = (localBounds.getWidth() < 0 || localBounds.getHeight() < 0) ? 0 : area;
3133 }
3134 return area * (camera.getViewWidth() / 2 * camera.getViewHeight() / 2);
3135 }
3136 return 0;
3137 }
3138
3139 /* *************************************************************************
4806 localToParentTx = localToParentTx.deriveWithTranslation(
4807 getTranslateX() + getLayoutX() + pivotX,
4808 getTranslateY() + getLayoutY() + pivotY,
4809 getTranslateZ() + pivotZ);
4810 localToParentTx = localToParentTx.deriveWithRotation(
4811 Math.toRadians(getRotate()), getRotationAxis().getX(),
4812 getRotationAxis().getY(), getRotationAxis().getZ());
4813 localToParentTx = localToParentTx.deriveWithScale(
4814 getScaleX(), getScaleY(), getScaleZ());
4815 localToParentTx = localToParentTx.deriveWithTranslation(
4816 -pivotX, -pivotY, -pivotZ);
4817 } else {
4818 localToParentTx = localToParentTx.deriveWithTranslation(
4819 getTranslateX() + getLayoutX(),
4820 getTranslateY() + getLayoutY(),
4821 getTranslateZ());
4822 }
4823
4824 if (impl_hasTransforms()) {
4825 for (Transform t : getTransforms()) {
4826 localToParentTx = TransformHelper.derive(t, localToParentTx);
4827 }
4828 }
4829
4830 // Check to see whether the node requires mirroring
4831 if (mirror) {
4832 localToParentTx = localToParentTx.deriveWithTranslation(
4833 mirroringCenter, 0);
4834 localToParentTx = localToParentTx.deriveWithScale(
4835 -1.0, 1.0, 1.0);
4836 localToParentTx = localToParentTx.deriveWithTranslation(
4837 -mirroringCenter, 0);
4838 }
4839
4840 transformDirty = false;
4841 }
4842 }
4843
4844 /**
4845 * Transforms in place the specified point from parent coords to local
4846 * coords. Made package private for the sake of testing.
6075 public Object getBean() {
6076 return Node.this;
6077 }
6078
6079 @Override
6080 public String getName() {
6081 return "rotationAxis";
6082 }
6083 };
6084 }
6085 return rotationAxis;
6086 }
6087
6088 public ObservableList<Transform> getTransforms() {
6089 if (transforms == null) {
6090 transforms = new TrackableObservableList<Transform>() {
6091 @Override
6092 protected void onChanged(Change<Transform> c) {
6093 while (c.next()) {
6094 for (Transform t : c.getRemoved()) {
6095 TransformHelper.remove(t, Node.this);
6096 }
6097 for (Transform t : c.getAddedSubList()) {
6098 TransformHelper.add(t, Node.this);
6099 }
6100 }
6101
6102 impl_transformsChanged();
6103 }
6104 };
6105 }
6106
6107 return transforms;
6108 }
6109
6110 public boolean canSetTranslateX() {
6111 return (translateX == null) || !translateX.isBound();
6112 }
6113
6114 public boolean canSetTranslateY() {
6115 return (translateY == null) || !translateY.isBound();
6116 }
6117
6118 public boolean canSetTranslateZ() {
|