ラベル JavaFX の投稿を表示しています。 すべての投稿を表示
ラベル JavaFX の投稿を表示しています。 すべての投稿を表示

2009年1月8日木曜日

JavaFX PullParser (data.pull)

JavaFX で XML をパースしてみる

javafx.data.pull.PullParser は XML と JSON は最初からサポートされている

ここ がわかりやすかった

こんな XML をパースすると
More...
sandwich.xml














import java.io.FileInputStream;
import javafx.data.pull.Event;
import javafx.data.pull.PullParser;
import javafx.ext.swing.SwingList;
import javafx.ext.swing.SwingListItem;
import javafx.scene.Scene;
import javafx.stage.Stage;

var list = SwingList { width: 600 height: 300 }

var myparser = PullParser {
documentType: PullParser.XML;
onEvent: function (e: Event) {
var item = SwingListItem {
text: "event {e}"
};
insert item into list.items;
}
input: new FileInputStream("/tmp/sandwich.xml");
}
myparser.parse();

Stage {
title: "XML Sandwich"
scene: Scene { content: list }
}


e : Event の中身がリストになって出力される
結果は ここ

Event の要素は data.pull.Event に定義されている

variables
type : Integer current Event type
typeName : String current Event name
level : Integer depth of Node
qname : QName name of XML element
text : String XML text

variable of QName (javafx.data.xml.QName)
name : String
namespaces : String

functions
getAttributeValue(qname : QName) : String



type はこんな感じで使う
if(e.type == PullParser.START_ELEMENT){
...
}

variables of PullParser
START_DOCUMENT : Integer (=7)
END_DOCUMENT : Integer (=8)
START_ELEMENT : Integer (=1)
END_ELEMENT : Integer (=2)
TEXT : Integer (=4)


qname はこんな感じで使う
if(e.qname.name.equals("bread")){
...
}

xml が
<cheese type="chedar"/>
のようになっているとき、 getAttributeValue で type の値を得る

if(e.qname.name.equals("cheese")){
var cheesetype = e.getAttributeValue(QName{name:"type"});
// cheesetype = "chedar" になる
....
}

2009年1月7日水曜日

JavaFX HttpRequest (io.http)

JavaFX で http リクエスト

GET request


var s : String = "";

def request : HttpRequest = HttpRequest {
location: "http://javafx.com";

onStarted: function() {
s = "started"
}
onConnecting: function() {
s = "{s}\nconnecting..."
}
onDoneConnect: function() {
s = "{s}\ndoneConnect"
}
onReadingHeaders: function() {
s = "{s}\nreadingHeaders..."
}
onResponseCode: function(code:Integer) {
s = "{s}\nresponseCode: {code}"
}
onResponseMessage: function(msg:String) {
s = "{s}\nresponseMessage: {msg}"
}

onResponseHeaders: function(headerNames: String[]) {
s = "{s}\nthere are {headerNames.size()} response headers:";
for (name in headerNames) {
s = "{s}\n {name}: {request.getResponseHeaderValue(name)}"
}
}

onToRead: function(bytes: Integer) {
s = "{s}\nbytes to read: {bytes}"
}

onRead: function(bytes: Integer) {
def progress =
if (request.toread > 0) "({(bytes * 100 / request.toread)}%)" else "";
s = "{s}\nbytes read: {bytes} {progress}";
}

onInput: function(is: java.io.InputStream) {
try {
s = "{s}\nbytes of content available: {is.available()}"
} finally {
is.close();
}
}

onException: function(ex: Exception) {
s = "exception: {ex.toString()}"
}
onDoneRead: function() {
s = "{s}\ndoneRead"
}
onDone: function() {
s = "{s}\ndone"
}
}

Stage {
title: "MyApp"
scene: Scene {
width: 400
height: 600
content:Text {
font: Font {
size: 11
}
x: 10,
y: 30
content: bind s
}
}
}

request.enqueue();



実行結果



variables
input : InputStream
location : "http://javafx.com"
method : String ("GET/POST/PUT/DELETE")
output : OutputStream (only POST or PUT)
POST : String (only method = POST)
PUT : String (only method = PUT)
read : Integer (read bytes)
responseCode : Integer
responseMessage : String
toread : Integer (be expected read bytes)
towrite : Integer (going to be written bytes)
written : Integer (have been written bytes)


triggers
onStarted: function() {}
onConnecting: function() {}
onDoneConnect: function() {}
onReadingHeaders: function() {}
onResponseCode: function(code:Integer) {}
onResponseMessage: function(msg:String) {}
onResponseHeaders: function(headerNames: String[]) {}
onToRead: function(bytes: Integer) {}
onRead: function(bytes: Integer) {}

// Be sure to close the input sream when finished
onInput: function(input: java.io.InputStream) {
try {

} finally {
is.close();
}
}

onException: function(ex: Exception) {}
onDoneRead: function() {}
onDone: function() {}

JavaFX TextBox (scene.control)

Swing の TextField も使えるが、 JavaFX のクラスで TextBox が用意されている


import javafx.scene.control.*;
import javafx.scene.*;
import javafx.stage.*;
Stage {
scene: Scene {
content: TextBox {
text: "Hello World"
columns: 12
selectOnFocus: true
}
}
}


変数には
coulmns : Number
editable : Boolean
selectOnFocus : Boolean
text : String (編集と同時に update)
value : String (focus lost 時 or Enter press 時に update)

2009年1月6日火曜日

JavaFX javafx.io.http

JavaFX で http request の結果を取得するには、

JavaFX.io.http の
HttpHeader
HttpRequest
HttpStatus
を使うべし
More...

2009年1月5日月曜日

JavaFX TranslateTransition (animation.transition)


import javafx.animation.transition.TranslateTransition;

var node = Rectangle {
x: 100,
y: 40
width: 100,
height: 100
arcHeight: 50
arcWidth: 50
fill: Color.VIOLET
}

var transTransition = TranslateTransition {
duration : 2s
node : node
fromY : 0
toY : 200
repeatCount : 4
autoReverse : true
}

transTransition.play();


byX : x (startX + x まで移動)
byY : y (startY + y まで移動)
fromX : x (x から移動)
fromY : y (y から移動)
toX : x (x へ移動)
toY : y (y へ移動)

autoReverse : true/false
currentRate : 1/-1
duration : time (移動にかける時間)
interpolate : Interpolator.EASEBOTH (始点と終点付近で減速・加速する)
repeatCount : count (繰り返しの回数)

2008年12月24日水曜日

JavaFX FX (lang)

public static java.lang.Object getArgument(java.lang.String name)

現在のJavaFX Script program の incoming argument を返す。特に name/value 対の incoming argument applets の環境をチェックするのに使える。
たいていは String が返ってくるが、ある環境では他の値が返ってくる可能性がある。
String 形式の数字を受け入れる (e.g. getArgument("0"))。引数の名前の argument がない場合は null を返す。

getArgument("javafx.applet") はブラウザ内で JavaFX script application を走らせるためのapplet を返す。

次のように使える

var applet = FX.getArgument("javafx.applet") as java.applet.Applet;
var inBrowser = "true".equals(FX.getArgument("isApplet") as String);

一度この applet が得られると、次の4つの使い方がある。

to invoke AppletContext's showDocument() method(s)
to invoke AppletContext's showStatus() method
to retrieve the JSObject to interact with JavaScript in the page
to retrieve the DOM object using bootstrapping mechanism in the new plugin

applet として走っていない場合、 getArgument("javafx.applet") は null を返す

More...

2008年12月23日火曜日

JavaFX Stage (scene)

Stage の Style を変える

・default
style : StageStyle.DECORATED


import javafx.stage.Stage
import javafx.stage.StageStyle

Stage {
title: "Application title"
width: 250
height: 80
scene: Scene {
content: Text {
font : Font { size : 24 }
x: 10, y: 30
content: "Application content"
}
}
style: StageStyle.DECORATED
}





・透明な背景 & 縁なし
style : StageStyle.TRANSPARENT





・白い背景 & 縁なし
style : StageStyle.UNDECORATED

2008年12月20日土曜日

JavaFX Example

More...

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

Stage {
title: "Declaring Is Easy!"
width: 249
height: 251
visible: true
scene: Scene {
content: [
Circle {
centerX: 118
centerY: 110
radius: 83
fill: Color.WHITE
stroke: Color.RED
},
Rectangle {
x: 45 y: 35
width: 150 height: 150
arcWidth: 15 arcHeight: 15
fill: Color.GREEN
}
]
}
}



More...

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.text.Text;
import javafx.scene.transform.Transform;

Stage {
title: "Nodes"
width: 220
height: 170
visible: true
scene: Scene {
fill: Color.LIGHTBLUE
content: Group {
translateX: 55
translateY: 10
content: [
Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
},
Text {
transforms: Transform.rotate(33, 10, 100)
content: "Duke"
},
ImageView {
image: Image {url: "http://java.sun.com/docs/books/tutorial/uiswing/examples/components/TextSamplerDemoProject/src/components/images/dukeWaveRed.gif"}
}
]
}
}
}



More...

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Circle;
import javafx.scene.effect.Reflection;

Stage {
title: "JavaFX Record Button"
width: 249
height: 251
visible: true
scene: Scene {
fill: LinearGradient {
startX: 0, startY: 0, endX: 0, endY: 1.0, proportional: true
stops: [
Stop {offset: 0.0 color: Color.WHITE},
Stop {offset: 1.0 color: Color.BLACK}
]
}
content: [
Group{
content: [
Rectangle {
x: 40 y: 55 width: 150 height: 50
arcWidth: 20 arcHeight: 55 stroke: Color.BLACK
fill: LinearGradient {
startX: 0.0
startY: 0.0
endX: 0.0
endY: 1.0
proportional: true
stops: [
Stop {offset: 0.0 color: Color.WHITE},
Stop {offset: 1.0 color: Color.BLACK}
]
}
},
Circle {
centerX: 115 centerY: 80 radius: 15
fill: Color.web("#ff3300") stroke: Color.DARKRED
}
]
effect: Reflection {fraction: 0.9 topOpacity: 0.5 topOffset: 2.5}
}
]
}
}



More...

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.ext.swing.SwingSlider;

import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.paint.Stop;
import javafx.scene.paint.RadialGradient;

var slider = SwingSlider{
minimum: 0
maximum: 60
value: 0
translateX: 10
translateY: 110
};

Stage {
title: "Data Binding"
width: 220
height: 170
scene: Scene {
fill: Color.LIGHTGRAY;
content: [
slider,
Circle {
centerX: bind slider.value+50 centerY: 60 radius: 50
stroke: Color.YELLOW
fill: RadialGradient {
centerX: 50 centerY: 60 radius: 50
focusX: 50 focusY: 30
proportional: false
stops: [
Stop {offset: 0 color: Color.RED},
Stop {offset: 1 color: Color.WHITE},
]
}
}
]
}
visible: true
}



More...

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.ext.swing.SwingToggleGroup;
import javafx.ext.swing.SwingRadioButton;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;

var group = SwingToggleGroup{};

var choice1 = SwingRadioButton{
text: "STOP"
foreground: Color.GRAY
font: Font{name:"Tahoma" size: 15}
toggleGroup: group
};

var choice2 = SwingRadioButton{
text: "READY"
foreground: Color.GRAY
font: Font{name:"Tahoma" size: 15}
toggleGroup: group
};

var choice3 = SwingRadioButton{
text: "GO"
foreground: Color.GRAY
font: Font{name:"Tahoma" size: 15}
toggleGroup: group
};

var lightStop = Circle {
centerX: 12
centerY: 12
radius: 12
stroke: Color.GRAY
fill: bind RadialGradient {
centerX: 8,
centerY: 8,
radius: 12,
proportional: false
stops: [
Stop {offset: 0.0 color: Color.WHITE}
Stop {offset: 1.0 color:
if (choice1.selected)
then Color.RED
else Color.GREY
}
]
}
};

var lightReady = Circle {
centerX: 12
centerY: 12
radius: 12
stroke: Color.GRAY
fill: bind RadialGradient {
centerX: 8,
centerY: 8,
radius: 12,
proportional: false
stops: [
Stop {offset: 0.0 color: Color.WHITE}, Stop {offset: 1.0 color:
if (choice2.selected)
then Color.GOLD
else Color.GRAY
}
]
}
};

var lightGo = Circle {
centerX: 12
centerY: 12
radius: 12
stroke: Color.GRAY
fill: bind RadialGradient {
centerX: 8,
centerY: 8,
radius: 12,
proportional: false
stops: [
Stop {offset: 0.0 color: Color.WHITE},
Stop {offset: 1.0 color:
if (choice3.selected)
then Color.GREEN
else Color.GREY
}
]
}
};

Stage {
title: "Lights"
width: 220
height: 130
visible: true
scene: Scene{
fill: Color.HONEYDEW
content: HBox{
spacing: 10
content:[
VBox{
spacing: 10
content:[choice1, choice2, choice3]
},
HBox{
spacing: 15
content:[lightStop, lightReady, lightGo]
translateY: 25
}
]
}//HBox
} //Scene
}//Stage



More...

import javafx.animation.Interpolator;
import javafx.animation.Timeline;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.shape.ArcTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.effect.Lighting;
import javafx.scene.effect.light.DistantLight;

var x: Number;

Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at (0s) {x => 0.0},
at (7s) {x => 387.0 tween Interpolator.LINEAR},
]
}.play();

var y: Number;

Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at (0s) {y => 0.0},
at (4s) {y => 55.0 tween Interpolator.LINEAR},
]
}.play();

Stage{
title: "Cloud"
visible: true
scene: Scene{
fill: Color.WHITE
content:[
ImageView{
image: Image{url: "http://java.sun.com/docs/books/tutorial/2d/basic2d/examples/images/weather-sun.png"}
},
Path {
translateX: bind x
translateY: bind y
fill: Color.WHITE
stroke: Color.LIGHTBLUE
strokeWidth: 2
effect: Lighting{light: DistantLight{azimuth: 90}}
elements: [
MoveTo { x: 15 y: 15 },
ArcTo { x: 50 y: 10 radiusX: 20 radiusY: 20 sweepFlag: true},
ArcTo { x: 70 y: 20 radiusX: 20 radiusY: 20 sweepFlag: true},
ArcTo { x: 50 y: 60 radiusX: 20 radiusY: 20 sweepFlag: true},
ArcTo { x: 20 y: 50 radiusX: 10 radiusY: 5 sweepFlag: true},
ArcTo { x: 15 y: 15 radiusX: 10 radiusY: 10 sweepFlag: true},
]
}//Path
]
}//Scene
onClose: function() {
java.lang.System.exit(0);
}//close action
}//Stage



More...

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import javafx.scene.effect.DropShadow;
import javafx.scene.shape.Path;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.LineTo;
import javafx.scene.paint.RadialGradient;
import javafx.scene.shape.Rectangle;
import javafx.scene.effect.Lighting;
import javafx.scene.effect.Glow;
import javafx.scene.effect.light.DistantLight;
import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.MouseButton;

var effect = Glow{};
var visiblePlay: Boolean = true;
var visiblePause: Boolean = false;
var play: Boolean = false;

Stage {
title: "FXButton"
width: 170 height: 170
visible: true
scene: Scene {
fill: LinearGradient {
startX: 0, startY: 0, endX: 1, endY: 1, proportional: true
stops: [
Stop {offset: 0.0 color: Color.WHITE},
Stop {offset: 1.0 color: Color.GRAY}
]
}
content: [
Group{
cursor: Cursor.HAND
effect: effect
content: [
Circle {
centerX: 70
centerY: 70
radius: 40
fill:LinearGradient {
startX: 0
startY: 0
endX: 1
endY: 1
stops: [
Stop { offset:0 color: Color.web("#0099CC") },
Stop { offset:1 color: Color.web("#000099") }
]
}
effect: DropShadow{
offsetX: 5
offsetY: 5
color: Color.BLACK
}
},
Circle {
centerX: 70
centerY: 70
radius: 34
fill: bind RadialGradient {
centerX:0.5
centerY:0.5
radius:0.5
stops: [
Stop { offset:0 color: Color.web("#0099CC",0) },
Stop { offset:1 color: Color.web("#0099CC",1.0) }
]
}
effect: DropShadow{
offsetX: 2
offsetY: 2
color: Color.BLACK
}
},
Path{
visible: bind visiblePlay;
fill: Color.BLACK
elements: [
MoveTo { x: 63 y: 53 }, LineTo { x: 63 y: 84},
LineTo { x: 83 y: 68 }, LineTo {x: 63 y:53}
]
effect: Lighting{ light: DistantLight{azimuth: 90}}
},
Rectangle {
visible: bind visiblePause;
x: 57 y: 53 width: 9 height: 30
stroke: Color.BLACK fill: Color.BLACK
effect: Lighting{ light: DistantLight{azimuth: 90}}
},
Rectangle {
visible: bind visiblePause;
x: 73 y: 53 width: 9 height: 30
stroke: Color.BLACK fill: Color.BLACK
effect: Lighting{ light: DistantLight{azimuth: 90}}
},
]

onMouseEntered: function(evt: MouseEvent):Void {
effect.level = 0.65;
}

onMouseClicked: function(evt: MouseEvent):Void {
if(evt.button == MouseButton.PRIMARY) {
if(play == true){
visiblePlay = true;
visiblePause = false;
play = false
}
else{
visiblePlay = false;
visiblePause = true;
play = true;
}
}
}

onMousePressed: function(evt: MouseEvent):Void {
if(evt.button == MouseButton.PRIMARY) {
effect.level = 0.0;
}
}

onMouseReleased: function(evt: MouseEvent):Void {
effect.level = 0.65;
}

onMouseExited: function(evt: MouseEvent):Void {
effect.level = 0.3;
}
},
]
}
}

JavaFX Cursor (scene.Cursor)

Cursor カーソル

Circle{
centerX: 30
centerY: 40
radius: 20
fill: Color.RED
opacity: 0.8
cursor: Cursor.HAND
};

/**
Cursor.CROSSHAIR
Cursor.DEFAULT
Cursor.E_RESIZE
Cursor.H_RESIZE
Cursor.MOVE
Cursor.N_RESIZE
Cursor.NE_RESIZE
Cursor.NONE
Cursor.NW_RESIZE
Cursor.S_RESIZE
Cursor.SE_RESIZE
Cursor.SW_RESIZE
Cursor.TEXT
Cursor.V_RESIZE
Cursor.W_RESIZE
Cursor.WAIT
*/

JavaFX Perspective Transformation (scene.transform)

Perspective Transform 遠近変形

ImageView{
image: Image {
url: "{__dir__}image.gif"
}
effect: PerspectiveTransform {
ulx: 60
uly: 0
urx: 100
ury: 0
lrx: 100
lry: 115
llx: 30
lly: 100
}
}

JavaFX Scaling (scene.transform)

Scaling 拡大/縮小

Circle {
centerX: 20
centerY: 20
radius:20
fill: Color.RED
transforms: Transform.scale(2, 2);
}

JavaFX ShearTransformation (scene.transform)

Shear Transformation 引きのばし

ImageView{
transforms: Transform.shear(2, 1);
image: Image {
url: "{__dir__}image.gif"
}
}

JavaFX Translate (scene.transform)

Translate 移動

Text{
content:"Step by step"
transforms: Transform.translate(15, 30);
}

JavaFX Rotation (scene.transform)

Rotate 回転

ImageView{
image: Image{
url: "{__dir__}image.gif"
}
transforms: Rotate {
angle: 60
pivotX: 40
pivotY: 400
}
};

JavaFX Color Adjust (scene.effect)

Color Adjust 色調整

var brightness = ImageView{
image: Image{"{__dir__}image.gif"}
effect: ColorAdjust{brightness: -0.2}
};

var contrast = ImageView{
image: Image{"{__dir__}image.gif"}
effect: ColorAdjust{contrast: 2}
};

var hue = ImageView{
image: Image{"{__dir__}image.gif"}
effect: ColorAdjust{hue: 1.0}
};

var saturation = ImageView{
image: Image{"{__dir__}image.gif"}
effect: ColorAdjust{saturation: 0.5}
};

JavaFX Sepia Tone (scene.effect)

Sepia Tone セピア

var sepia = ImageView{
image: Image{"{__dir__}image.gif"}
effect: SepiaTone {level: 0.8}
};

JavaFX Glow (scene.effect)

Glow 輝き

var glow = ImageView{
image: Image {"{__dir__}image.gif"}
effect: Glow {level: 1 }
};

JavaFX Reflection (scene.effect)

Reflection 反射


var reflection = Text {
x: 10
y: 42
content: "Reflection"
fill: Color.SEAGREEN
font: Font{ size: 20 name: "Verdana"}
effect: Reflection {
fraction: 0.9
topOpacity: 0.9
topOffset: 0.1
}
};

JavaFX Blur (scene.effect)

ぼかし

GaussianBlur

var blur1 = Rectangle{
x: 5
y: 25
width: 100
height: 50
fill: RadialGradient{
centerX: 55
centerY: 50
radius: 10
proportional: false
cycleMethod: CycleMethod.REFLECT
stops: [
Stop{offset: 0.3 color: Color.DARKGREEN},
Stop{offset: 1.0 color: Color.WHITE}
]
}
effect: GaussianBlur{radius: 5 }
};


MotionBlur

var blur2 = Rectangle{
x: 5
y: 25
width: 100
height: 50
fill: RadialGradient{
centerX: 55
centerY: 50
radius: 10
proportional: false
cycleMethod: CycleMethod.REFLECT
stops: [
Stop{offset: 0.3 color: Color.DARKGREEN},
Stop{offset: 1.0 color: Color.WHITE}
]
}
effect: MotionBlur{
angle: 45
input: InnerShadow {
offsetX: 4
offsetY: 4
radius: 6
color: Color.YELLOW
}
radius: 10
}
};

JavaFX Lighting (scene.effect)

離れた位置からのライティング

90度方向から

var lighting1 = Group{
content:[
Circle{
centerX: 30
centerY: 20
radius: 20
fill: Color.RED
opacity: 0.9
}
]
effect: Lighting{
light: DistantLight{azimuth: 90}}
};


270度方向から

var lighting2 = Group{
content:[
Circle{
centerX: 30
centerY: 20
radius:20
fill: Color.RED
opacity: 0.9
}
]
effect: Lighting{
light: DistantLight{azimuth: 270}}
};


1点からライティング

var lighting3 = Group{
content:[
Circle{
centerX: 30
centerY: 20
radius: 20
fill: Color.RED
opacity: 0.9
}
]
effect: Lighting{
light: PointLight{x: 20 y: 30 z: 50}}
};


スポットライト

var lighting4 = Group{
content:[
Circle{
centerX: 30
centerY: 20
radius: 20
fill: Color.RED
opacity: 0.9
}
]
effect: Lighting{
light: SpotLight {
x: 0
y: 10
z: 10
pointsAtX: 20
pointsAtY: 20
pointsAtZ: 0
specularExponent: 2
}
}
};