]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/AnimationContribution.java
git-svn-id: https://www.simantics.org/svn/simantics/3d/trunk@22283 ac1ea38d-2e2b...
[simantics/3d.git] / org.simantics.proconf.g3d.shapeeditor / src / org / simantics / proconf / g3d / shapeeditor / tools / AnimationContribution.java
diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/AnimationContribution.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/AnimationContribution.java
deleted file mode 100644 (file)
index 1b413c0..0000000
+++ /dev/null
@@ -1,784 +0,0 @@
-/*******************************************************************************\r
- * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.proconf.g3d.shapeeditor.tools;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.List;\r
-\r
-import javax.vecmath.AxisAngle4d;\r
-import javax.vecmath.Quat4d;\r
-\r
-import org.eclipse.jface.action.IMenuManager;\r
-import org.eclipse.jface.action.IToolBarManager;\r
-import org.eclipse.jface.dialogs.Dialog;\r
-import org.eclipse.jface.dialogs.InputDialog;\r
-import org.eclipse.jface.dialogs.MessageDialog;\r
-import org.eclipse.jface.viewers.ISelectionChangedListener;\r
-import org.eclipse.jface.viewers.SelectionChangedEvent;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.custom.CCombo;\r
-import org.eclipse.swt.events.FocusAdapter;\r
-import org.eclipse.swt.events.FocusEvent;\r
-import org.eclipse.swt.events.KeyAdapter;\r
-import org.eclipse.swt.events.KeyEvent;\r
-import org.eclipse.swt.events.SelectionAdapter;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.layout.FillLayout;\r
-import org.eclipse.swt.layout.FormAttachment;\r
-import org.eclipse.swt.layout.FormData;\r
-import org.eclipse.swt.layout.FormLayout;\r
-import org.eclipse.swt.layout.GridData;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Button;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Slider;\r
-import org.eclipse.swt.widgets.Text;\r
-import org.simantics.db.ContextGraph;\r
-import org.simantics.db.Graph;\r
-import org.simantics.db.GraphRequestAdapter;\r
-import org.simantics.db.GraphRequestStatus;\r
-import org.simantics.db.GraphRequestWithResult;\r
-import org.simantics.db.Resource;\r
-import org.simantics.animation.stubs.Animation;\r
-import org.simantics.animation.stubs.Interpolator;\r
-import org.simantics.animation.stubs.ScalarInterpolator;\r
-import org.simantics.animation.stubs.SlerpInterpolator;\r
-import org.simantics.layer0.utils.EntityFactory;\r
-import org.simantics.layer0.utils.IEntity;\r
-import org.simantics.layer0.utils.Property;\r
-import org.simantics.animation.curve.SlerpCurve;\r
-import org.simantics.animation.curve.TCBCurve;\r
-import org.simantics.proconf.g3d.actions.ContextAction;\r
-import org.simantics.proconf.g3d.actions.RotateAction;\r
-import org.simantics.proconf.g3d.actions.TranslateAction;\r
-import org.simantics.proconf.g3d.animation.Animatable;\r
-import org.simantics.proconf.g3d.base.EditorContribution;\r
-import org.simantics.proconf.g3d.base.G3DTools;\r
-import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
-import org.simantics.proconf.g3d.base.VisualizationScheduler;\r
-import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
-import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
-import org.simantics.proconf.g3d.scenegraph.ISelectableNode;\r
-import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources;\r
-import org.simantics.proconf.g3d.shapeeditor.dialogs.PropertySelectionDialog;\r
-import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase;\r
-import org.simantics.proconf.g3d.stubs.G3DModel;\r
-import org.simantics.proconf.g3d.stubs.Orientation;\r
-import org.simantics.utils.ui.ErrorLogger;\r
-\r
-public class AnimationContribution implements EditorContribution {\r
-       List<ContextAction> actions = new ArrayList<ContextAction>();\r
-       \r
-       private ShapeEditorBase parent;\r
-       \r
-       private final String NO_ANIMATION = "None";\r
-\r
-       private Slider timeSlider;\r
-       private double key = 0;\r
-       private Composite buttonComposite;\r
-       private Button insertKeyFrameButton;\r
-       private Button clearKeyFrameButton;\r
-       private CCombo animationCombo;\r
-       private Button addAnimationButton;\r
-       private Button removeAnimationButton;\r
-       private Button clearAnimationButton;\r
-       private Button animateButton;\r
-       private Button usePrecalculation;\r
-       private Text timeText;\r
-       private Composite infoComposite;\r
-       private Text infoText;\r
-\r
-       private Resource animationResource;\r
-       \r
-       private ContextAction translateAction;\r
-       private ContextAction rotateAction;\r
-       \r
-       public AnimationContribution(ThreeDimensionalEditorBase parent) {\r
-               this.parent = (ShapeEditorBase)parent;\r
-       }\r
-       \r
-       @Override\r
-       public String getName() {\r
-               return "Animator";\r
-       }\r
-       \r
-       @Override\r
-       public void createControl(Composite parent) {\r
-               FormLayout flayout = new FormLayout();\r
-               parent.setLayout(flayout);\r
-               infoComposite = new Composite(parent, SWT.BORDER);\r
-               FormData data = new FormData();\r
-               data.top = new FormAttachment(0, 0);\r
-               data.left = new FormAttachment(0, 0);\r
-               data.right = new FormAttachment(100, 0);\r
-               data.bottom = new FormAttachment(infoComposite, 0, SWT.TOP);\r
-               this.parent.getRenderingComposite().setLayoutData(data);\r
-\r
-               infoComposite.setLayout(new FillLayout(SWT.VERTICAL));\r
-               infoText = new Text(infoComposite, SWT.NONE);\r
-               GridLayout layout = new GridLayout(2, false);\r
-               layout.horizontalSpacing = 2;\r
-               layout.verticalSpacing = 2;\r
-               layout.marginWidth = 1;\r
-               layout.marginHeight = 1;\r
-               infoComposite.setLayout(layout);\r
-               GridData gdata = new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1);\r
-               // FIXME : allows text widget to take all available space (horizontal / width)\r
-               gdata.widthHint = 2000;\r
-               infoText.setLayoutData(gdata);\r
-               timeSlider = new Slider(infoComposite, SWT.NONE);\r
-               timeSlider.setValues(0, 0, 100, 1, 1, 1);\r
-               timeSlider.addSelectionListener(new SelectionAdapter() {\r
-                       @Override\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               key = ((double) timeSlider.getSelection()) / 100.0;\r
-                               updateTime();\r
-                       }\r
-               });\r
-               timeSlider.setLayoutData(new GridData(SWT.FILL, 1, true, false));\r
-               timeText = new Text(infoComposite, SWT.SINGLE);\r
-               timeText.addFocusListener(new FocusAdapter() {\r
-                       @Override\r
-                       public void focusLost(FocusEvent e) {\r
-                               updateTime();\r
-                       }\r
-               });\r
-               timeText.addKeyListener(new KeyAdapter() {\r
-                       @Override\r
-                       public void keyReleased(KeyEvent e) {\r
-                               if (e.keyCode == SWT.CR)\r
-                                       updateTime();\r
-                       }\r
-               });\r
-\r
-               buttonComposite = new Composite(infoComposite, SWT.NONE);\r
-               buttonComposite.setLayout(new FillLayout(SWT.HORIZONTAL));\r
-               buttonComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1));\r
-               insertKeyFrameButton = new Button(buttonComposite, SWT.PUSH);\r
-               insertKeyFrameButton.setText("Insert Keyframe");\r
-               insertKeyFrameButton.addSelectionListener(new SelectionAdapter() {\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               insertKeyFrame();\r
-                       }\r
-               });\r
-\r
-               clearKeyFrameButton = new Button(buttonComposite, SWT.PUSH);\r
-               clearKeyFrameButton.setText("Clear Keyframe");\r
-\r
-               animationCombo = new CCombo(buttonComposite, SWT.NONE);\r
-               animationCombo.add(NO_ANIMATION);\r
-               animationCombo.select(0);\r
-               animationCombo.setEditable(false);\r
-               animationCombo.addSelectionListener(new SelectionAdapter() {\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               selectAnimation();\r
-                       }\r
-               });\r
-\r
-               addAnimationButton = new Button(buttonComposite, SWT.PUSH);\r
-               addAnimationButton.setText("New Animation");\r
-               addAnimationButton.addSelectionListener(new SelectionAdapter() {\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               addAnimation();\r
-                       }\r
-               });\r
-\r
-               clearAnimationButton = new Button(buttonComposite, SWT.PUSH);\r
-               clearAnimationButton.setText("Clear Animation");\r
-               clearAnimationButton.addSelectionListener(new SelectionAdapter() {\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               clearAnimation();\r
-                       }\r
-               });\r
-\r
-               removeAnimationButton = new Button(buttonComposite, SWT.PUSH);\r
-               removeAnimationButton.setText("Remove Animation");\r
-               removeAnimationButton.addSelectionListener(new SelectionAdapter() {\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               removeAnimation();\r
-                       }\r
-               });\r
-\r
-               animateButton = new Button(buttonComposite, SWT.TOGGLE);\r
-               animateButton.setText("Animate");\r
-               animateButton.addSelectionListener(new SelectionAdapter() {\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               animate();\r
-                       }\r
-               });\r
-\r
-               usePrecalculation = new Button(buttonComposite, SWT.CHECK);\r
-               usePrecalculation.setText("Precalc");\r
-\r
-               data = new FormData();\r
-               data.left = new FormAttachment(0, 0);\r
-               data.right = new FormAttachment(100, 0);\r
-               data.bottom = new FormAttachment(100, 0);\r
-               // FIXME : take account font size\r
-               data.height = 20 * 3;\r
-               infoComposite.setLayoutData(data);\r
-\r
-               this.parent.getSelectionAdapter().addSelectionChangedListener(new ISelectionChangedListener() {\r
-                       public void selectionChanged(SelectionChangedEvent event) {\r
-                               updateUI();\r
-                       }\r
-               });\r
-               updateUI();\r
-               \r
-               this.parent.getSession().asyncRead(new GraphRequestAdapter() {\r
-                       @Override\r
-                       public GraphRequestStatus perform(Graph g) throws Exception {\r
-                               G3DModel m = new G3DModel(g,AnimationContribution.this.parent.getModelResource());\r
-                       Collection<Animation> animations = m.getAnimation();\r
-\r
-                       final List<String> animationNames = new ArrayList<String>();\r
-                       for (Animation a : animations) {\r
-                               animationNames.add(a.getName());\r
-                       }\r
-                       AnimationContribution.this.parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {\r
-                               public void run() {\r
-                                       for (String s : animationNames)\r
-                                               animationCombo.add(s);\r
-                               }\r
-                       });\r
-                       return GraphRequestStatus.transactionComplete();\r
-                       }\r
-                       \r
-               });\r
-       }\r
-       \r
-       @Override\r
-       public void disposeControl() {\r
-               if (animateRunnable != null)\r
-               VisualizationScheduler.getInstance().removeVisualization(animateRunnable);\r
-       animateRunnable = null;\r
-       \r
-       infoComposite.dispose();\r
-\r
-       }\r
-       \r
-       @Override\r
-       public void fillContextMenu(Graph graph, IMenuManager manager, StructuredResourceSelection selection) {\r
-\r
-       }\r
-       \r
-       \r
-       \r
-       @Override\r
-       public Collection<ContextAction> getActions() {\r
-               return actions;\r
-       }\r
-       \r
-       @Override\r
-       public void initialize(Graph graph) {\r
-               actions.add(translateAction = new TranslateAction(parent) {\r
-                       @Override\r
-                       public void setInfoText(String text) {\r
-                               infoText.setText(text);\r
-                       }\r
-               });\r
-               actions.add(rotateAction = new RotateAction(parent){\r
-                       @Override\r
-                       public void setInfoText(String text) {\r
-                               infoText.setText(text);\r
-                       }\r
-               });\r
-       }\r
-       \r
-       private double getCurrentKey() {\r
-       return key;\r
-    }\r
-    \r
-    private void updateTime() {\r
-        final double t = getCurrentKey();\r
-        timeText.setText(Double.toString(t));\r
-        if (animationResource == null)\r
-            return;\r
-        if (usePrecalculation.getSelection()) {\r
-            for (IGraphicsNode n : parent.getScenegraphAdapter().getNodes()) {\r
-                if (n instanceof Animatable) {\r
-                       // TODO : frame-rate dependent animations\r
-                    ((Animatable)n).animate(t,0.0);\r
-                }\r
-                parent.setViewChanged(true);\r
-            }    \r
-        } else {\r
-               parent.getSession().asyncWrite(new GraphRequestAdapter() {\r
-                       @Override\r
-                       public GraphRequestStatus perform(Graph g) throws Exception {\r
-                               Collection<IEntity> interpolators = getAnimation(g).getRelatedObjects(ShapeEditorResources.animationResource.HasInterpolator);\r
-                    for (IEntity i : interpolators) {\r
-                        if (i.isInstanceOf(ShapeEditorResources.animationResource.ScalarInterpolator)) {\r
-                            // TODO : creating curve each time when time is set is\r
-                            // slow. Curve should be cached\r
-                            TCBCurve c = (TCBCurve) ShapeEditorResources.curveBuilder.loadInterpolator(i);\r
-                            double out = c.evaluate(t);\r
-                            g.setScalarDouble(i.getSingleRelatedObject(ShapeEditorResources.animationResource.HasTarget).getResource(), out);\r
-                        } else if (i.isInstanceOf(ShapeEditorResources.animationResource.SlerpInterpolator)) {\r
-                            // TODO : creating curve each time when time is set is slow.\r
-                            // Curve should be cached\r
-                            SlerpCurve c = (SlerpCurve) ShapeEditorResources.curveBuilder.loadInterpolator(i);\r
-                            Quat4d out = c.evaluate(t);\r
-                            Orientation r = new Orientation(i.getSingleRelatedObject(ShapeEditorResources.animationResource.HasTarget));\r
-                            AxisAngle4d aa = new AxisAngle4d();\r
-                            aa.set(out);\r
-                            G3DTools.setOrientation(r, aa);\r
-                        }\r
-                    }\r
-                               return GraphRequestStatus.transactionComplete();\r
-                       }\r
-                       \r
-                       @Override\r
-                       public void requestCompleted(GraphRequestStatus status) {\r
-                               parent.getScenegraphAdapter().setChanged(true);\r
-                       }\r
-               });   \r
-        }\r
-    }\r
-    \r
-    private IEntity findPropertyInterpolator(Graph g, Resource property) {\r
-       Collection<IEntity> interpolators = getAnimation(g).getRelatedObjects(ShapeEditorResources.animationResource.HasInterpolator);\r
-        for (IEntity i : interpolators) {\r
-            IEntity e = i.getAtMostOneRelatedObject(ShapeEditorResources.animationResource.HasTarget);\r
-            if (e == null)\r
-                continue;\r
-            if (e.getResource().equals(property)) {\r
-                return i;\r
-            }\r
-        }\r
-        return null;\r
-    }\r
-    \r
-    private void insertKeyFrame() {\r
-       ArrayList<Resource> instances = new ArrayList<Resource>();\r
-       for (Resource rs : parent.getSelectionAdapter().getCurrentSelection().getSelectionList()) {\r
-               instances.add(rs);\r
-       }\r
-        PropertySelectionDialog dialog = new PropertySelectionDialog(parent.getRenderingComposite().getShell(),"Select property","Select animated property",parent.getSession(),instances);\r
-        if (dialog.open() == Dialog.CANCEL) {\r
-            return;\r
-        }\r
-        final List<Resource> properties = dialog.getSelectedPropertyInstances(); \r
-        parent.getSession().asyncWrite(new GraphRequestAdapter() {\r
-               @Override\r
-               public GraphRequestStatus perform(Graph g) throws Exception {\r
-                       for (Resource r : properties) {\r
-                               IEntity t = EntityFactory.create(g,r);\r
-                    IEntity current = findPropertyInterpolator(g, r);\r
-                    if (t.isInstanceOf(ShapeEditorResources.g3dResource.Position)) {\r
-                        \r
-                        for (int i = 0; i < 3; i++) {\r
-                               IEntity d = null;\r
-                            switch (i) {\r
-                            case 0:\r
-                                d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasX);\r
-                                break;\r
-                            case 1:\r
-                               d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasY);\r
-                               break;\r
-                            case 2:\r
-                               d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasZ);\r
-                               break;\r
-                            }\r
-                            current = findPropertyInterpolator(g, d.getResource());\r
-                            addScalarKey(current,d);\r
-                        }\r
-                        \r
-                    } else if (t.isInstanceOf(ShapeEditorResources.g3dResource.Orientation)) {\r
-                        Orientation rot = new Orientation(t);\r
-                        addSlerpKey(current, rot);\r
-                    } else if (t.isInstanceOf(ShapeEditorResources.g3dResource.Color)) {\r
-                        for (int i = 0; i < 3; i++) {\r
-                            IEntity d = null;\r
-                               switch (i) {\r
-                            case 0:\r
-                               d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasRed);\r
-                                break;\r
-                            case 1:\r
-                                break;\r
-                            case 2:\r
-                                break;\r
-                            }\r
-                            current = findPropertyInterpolator(g, d.getResource());\r
-                               addScalarKey(current,d);\r
-                        }\r
-                    } else if (t.isInstanceOf(g.getBuiltins().Double)) {\r
-                       addScalarKey(current,t);\r
-                    } else {\r
-                        // TODO: basic cases are handled, only way to support\r
-                        // is to find all doubles from property structure and\r
-                        // interpolators attached to them, if there's any\r
-                        ErrorLogger.getDefault().logWarning("Default keyframe adding has not been implemented", null);\r
-                    }\r
-                }\r
-                       return GraphRequestStatus.transactionComplete();\r
-               }\r
-        });\r
-    }\r
-    \r
-    private void addScalarKey(IEntity current, IEntity d) {\r
-        \r
-       Graph graph = d.getGraph();\r
-       if (current == null) {\r
-            current = ScalarInterpolator.createDefault(graph).toInterpolator(); // FIXME : stubcast\r
-            getAnimation(graph).addStatement(ShapeEditorResources.animationResource.HasInterpolator, current);\r
-            current.addStatement(ShapeEditorResources.animationResource.HasTarget, d);\r
-        }\r
-        ShapeEditorResources.curveBuilder.addKey(current,getCurrentKey(),new double[]{d.getGraph().getScalarDouble(d.getResource()),0.0,0.0,0.0});\r
-    }\r
-    \r
-    private void addSlerpKey(IEntity current, Orientation r) {\r
-        Graph graph = r.getGraph();\r
-       if (current == null) {\r
-            current = SlerpInterpolator.createDefault(graph).toInterpolator(); // FIXME : stubcast\r
-            getAnimation(graph).addStatement(ShapeEditorResources.animationResource.HasInterpolator, current);\r
-            current.addStatement(ShapeEditorResources.animationResource.HasTarget, r);\r
-            \r
-        }\r
-        AxisAngle4d aa = G3DTools.getOrientation(r);\r
-        Quat4d q = new Quat4d();\r
-        q.set(aa);\r
-        ShapeEditorResources.curveBuilder.addKey(current,getCurrentKey(),new double[]{q.w,q.x,q.y,q.z});  \r
-    }\r
-    \r
-    private void selectAnimation() {\r
-        if (animationCombo.getSelectionIndex() == 0) {\r
-            animationResource = null;\r
-            updateUI();\r
-        } else {\r
-               final String name = animationCombo.getItem(animationCombo.getSelectionIndex());\r
-               parent.getSession().asyncRead(new GraphRequestAdapter() {\r
-                       @Override\r
-                       public GraphRequestStatus perform(Graph g) throws Exception {\r
-                               \r
-                    Resource modelResource = parent.getModelResource();\r
-                    G3DModel m = new G3DModel(g, modelResource);\r
-                    Collection<Animation> animations = m.getAnimation();\r
-                    boolean found = false;\r
-                    for (Animation a : animations) {\r
-                        if (a.getName().startsWith(name) && a.getName().length() == name.length()) {\r
-                            animationResource = a.getResource();\r
-                            found = true;\r
-                            break;\r
-                        }\r
-                    }\r
-                    if (!found) {\r
-                        ErrorLogger.defaultLogError("Could find animation " + name + " for model " + m.getResource(), null);\r
-                        animationResource = null;\r
-                    }\r
-                               return GraphRequestStatus.transactionComplete();\r
-                       }\r
-                       @Override\r
-                       public void requestCompleted(GraphRequestStatus status) {\r
-                               parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {\r
-                                       @Override\r
-                                       public void run() {\r
-                                                updateUI();    \r
-                                       }\r
-                               });\r
-                       }\r
-               });\r
-        }       \r
-    }\r
-    \r
-    private Animation getAnimation(Graph graph) {\r
-       return new Animation(graph, animationResource);\r
-    }\r
-\r
-    private void addAnimation() {\r
-        InputDialog d = new InputDialog(parent.getRenderingComposite().getShell(),"Animation name","Animation name","",null);\r
-        if (d.open() == InputDialog.CANCEL) {\r
-            return;\r
-        }\r
-        final String name = d.getValue();\r
-        if (name == null || name.length() == 0) {\r
-            return;\r
-        }\r
-        parent.getSession().asyncWrite(new GraphRequestAdapter() {\r
-               @Override\r
-               public GraphRequestStatus perform(Graph g) throws Exception {\r
-                       G3DModel m = parent.getModel(g);\r
-                       Collection<IEntity> animations = m.getRelatedObjects(ShapeEditorResources.animationResource.HasAnimation);\r
-                       for (IEntity a : animations) {\r
-                        if (a.getName().startsWith(name) && a.getName().length() == name.length()) {\r
-                        ErrorLogger.getDefault().logWarning("Cannot add animation with the same name " + name, null);\r
-                        return GraphRequestStatus.transactionCancel();\r
-                    }\r
-                }\r
-\r
-                Animation newAnimation = Animation.createDefault(g);\r
-                newAnimation.setName(name);\r
-                m.addStatement(ShapeEditorResources.animationResource.HasAnimation, newAnimation);\r
-                \r
-                       return GraphRequestStatus.transactionComplete();\r
-               }\r
-\r
-               @Override\r
-               public void requestCompleted(GraphRequestStatus status) {\r
-                       parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {\r
-                               public void run() {\r
-                                       animationCombo.add(name);\r
-                        animationCombo.select(animationCombo.indexOf(name));\r
-                        selectAnimation();\r
-                               }\r
-                       });\r
-               }\r
-        });    \r
-    }\r
-    \r
-    private void removeAnimation() {\r
-        assert(animationResource != null);\r
-        GraphRequestWithResult<String> r = new GraphRequestWithResult<String>() {\r
-               public String performWithResult(Graph g) throws Exception {\r
-                       return getAnimation(g).getName();\r
-               };\r
-        };\r
-        parent.getSession().syncRead(r);\r
-        MessageDialog dialog = new MessageDialog(parent.getRenderingComposite().getShell(),"Confirm",null,"Do you want to remove animation " + r.getResult() ,MessageDialog.QUESTION,new String[]{"Yes","No"},1);\r
-        if (dialog.open() == 1)\r
-               return;\r
-        parent.getSession().asyncWrite(new GraphRequestAdapter() {\r
-               String name;\r
-               @Override\r
-               public GraphRequestStatus perform(Graph g) throws Exception {\r
-                       \r
-                       Animation currentAnimation = getAnimation(g);\r
-                       name = currentAnimation.getName();\r
-                parent.getModel(g).removeStatement(ShapeEditorResources.animationResource.HasAnimation, currentAnimation);\r
-                \r
-                       return GraphRequestStatus.transactionComplete();\r
-               }\r
-               \r
-               @Override\r
-               public void requestCompleted(GraphRequestStatus status) {\r
-                       parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {\r
-                               public void run() {\r
-                                       animationCombo.remove(animationCombo.indexOf(name));\r
-                               }\r
-                       });     \r
-               }\r
-        });\r
-    }\r
-    \r
-    private void clearAnimation() {\r
-        assert(animationResource != null);  \r
-        \r
-        parent.getSession().asyncWrite(new GraphRequestAdapter() {\r
-               \r
-               boolean proceed;\r
-               @Override\r
-               public GraphRequestStatus perform(Graph g) throws Exception {\r
-                       int size = getAnimation(g).getInterpolator().size();\r
-                       if (size == 0)\r
-                               return GraphRequestStatus.transactionCancel();\r
-                       final String name = getAnimation(g).getName();\r
-                       parent.getRenderingComposite().getDisplay().syncExec(new Runnable() {\r
-                               public void run() {\r
-                                       MessageDialog dialog = new MessageDialog(parent.getRenderingComposite().getShell(),"Confirm",null,"Do you want to clear animation " + name ,MessageDialog.QUESTION,new String[]{"Yes","No"},1);\r
-                           proceed = (dialog.open() != MessageDialog.CANCEL);\r
-                               }\r
-                       });\r
-                       if (proceed) {\r
-                               //getAnimation(g).getInterpolator().clear();\r
-                               getAnimation(g).removeRelatedStatements(ShapeEditorResources.animationResource.HasInterpolator);\r
-                               return GraphRequestStatus.transactionComplete();\r
-                       } else {\r
-                               return GraphRequestStatus.transactionCancel();\r
-                       }\r
-               }\r
-        });\r
-    }\r
\r
-    public Graph createAnimationParameterization(Graph g) {\r
-               if (g.getObjects(parent.getModelResource(), ShapeEditorResources.g3dResource.HasSizingParameter).size() > 0) {\r
-                       ContextGraph graph;\r
-                       if (!(g instanceof ContextGraph)) {\r
-                               graph = new ContextGraph(g);\r
-                               graph.setContext(parent.getModelResource());\r
-                       } else {\r
-                               graph = (ContextGraph)g;\r
-                       }\r
-                       Animation animation = getAnimation(graph);\r
-                       Collection<Interpolator> interpolators = animation.getInterpolator();\r
-                       for (org.simantics.animation.stubs.Interpolator interpolator : interpolators) {\r
-                       IEntity target = interpolator.getTarget();\r
-                       // check all model properties\r
-                       G3DModel model = parent.getModel(graph);\r
-                       Collection<Property> modelProperties = model.getRelatedProperties(ShapeEditorResources.g3dResource.HasSizingParameter);\r
-                       for (Property p : modelProperties) {\r
-                               IEntity t = EntityFactory.create(graph,p.getResource());\r
-                               // get parameterization equations\r
-                               Collection<IEntity> equations = t.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget);\r
-                               // get parameterized values\r
-                               Collection<IEntity> parameterTargets = new ArrayList<IEntity>();\r
-                               for (IEntity eq : equations) {\r
-                                       Collection<IEntity> tgts = eq.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget);\r
-                                       assert(tgts.size() == 1);\r
-                                       parameterTargets.add(tgts.iterator().next());\r
-                               }\r
-                               // do matching between interpolator targets and parameterized values\r
-                               // TODO : old system did not have inverse relations but current system does.\r
-                               //                it is possible to take interpolation target and find if it is connected to an equation\r
-                               //                this would make code much faster (no more stupid loops over everything)\r
-                               for (IEntity d : parameterTargets) {\r
-                                       if (d.getResource().equals(target.getResource())) {\r
-                                               // get default value for sizing property\r
-                                               Collection<IEntity> prop = t.getRelatedObjects(ShapeEditorResources.g3dResource.HasDefaultDoubleValue);\r
-                                               if (prop.size() == 1) {\r
-                                                       ShapeEditorResources.curveBuilder.parameterize(interpolator, prop.iterator().next().toProperty().getDoubleArray(), p.getDoubleArray());\r
-                                       } else {\r
-                                               ErrorLogger.defaultLogError("Cannot parameterize interpolator " + interpolator.getResource() + " of animation " + animation.getResource() + " since parameter " + p.getResource() + " has no default value", null);\r
-                                       }\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-                       \r
-                       return graph;\r
-               } else {\r
-                       return g;\r
-               }\r
-       }\r
-    \r
-    private AnimateRunnable animateRunnable = null;\r
-    \r
-    private void animate() {\r
-        updateUI();\r
-        if (animateButton.getSelection()) {\r
-            if (animateRunnable != null)\r
-                return;\r
-            if (usePrecalculation.getSelection()) {\r
-               parent.getSession().asyncRead(new GraphRequestAdapter() {\r
-                       @Override\r
-                       public GraphRequestStatus perform(Graph g) throws Exception {\r
-                               Graph graph = parent.createParameterization(g);\r
-                               createAnimationParameterization(graph);\r
-                               for (IGraphicsNode n : parent.getScenegraphAdapter().getNodes()) {\r
-                                       if (n instanceof ISelectableNode) {\r
-                                               if (!((ISelectableNode)n).isVisible())\r
-                                                       continue;\r
-                                       }\r
-                            if (n instanceof Animatable) {\r
-                                ((Animatable)n).setAnimation(graph,animationResource);\r
-                            }\r
-                        }\r
-                               return GraphRequestStatus.transactionComplete();\r
-                       }\r
-                       \r
-                       @Override\r
-                       public void requestCompleted(GraphRequestStatus status) {\r
-                               animateRunnable = new AnimateRunnable();\r
-                        VisualizationScheduler.getInstance().addVisualization(animateRunnable);\r
-                       }\r
-               });\r
-            } else {\r
-               animateRunnable = new AnimateRunnable();\r
-                VisualizationScheduler.getInstance().addVisualization(animateRunnable);\r
-            }\r
-            \r
-        } else {\r
-            if (animateRunnable == null)\r
-                return;       \r
-            VisualizationScheduler.getInstance().removeVisualization(animateRunnable);\r
-            animateRunnable = null;\r
-            if (usePrecalculation.getSelection()) {\r
-               // updateTime updates values to graph if precalculation is not used.\r
-               // we must store current values from animation to synchronize view and graph\r
-               // information so that use can modify animation properly.\r
-               usePrecalculation.setSelection(false);\r
-               updateTime();\r
-               usePrecalculation.setSelection(true);\r
-               for (IGraphicsNode n : parent.getScenegraphAdapter().getNodes()) {\r
-                  if (n instanceof Animatable) {\r
-                      ((Animatable)n).setAnimation(null,null);\r
-                  }\r
-              }\r
-            }\r
-        }\r
-    }\r
-    \r
-    private void updateUI() {\r
-        if (animationResource != null) {\r
-            animateButton.setEnabled(true);\r
-            timeSlider.setEnabled(true);\r
-            if (animateButton.getSelection()) {\r
-                addAnimationButton.setEnabled(false);\r
-                insertKeyFrameButton.setEnabled(false);\r
-                removeAnimationButton.setEnabled(false);\r
-                clearKeyFrameButton.setEnabled(false);\r
-                animationCombo.setEnabled(false);\r
-                usePrecalculation.setEnabled(false);\r
-                clearAnimationButton.setEnabled(false);\r
-            } else {\r
-                addAnimationButton.setEnabled(true);\r
-                insertKeyFrameButton.setEnabled(!parent.getSelectionAdapter().getCurrentSelection().isEmpty());\r
-                removeAnimationButton.setEnabled(true);\r
-                clearKeyFrameButton.setEnabled(false); //FIXME : detect keyframes\r
-                animationCombo.setEnabled(true);\r
-                usePrecalculation.setEnabled(true);\r
-                clearAnimationButton.setEnabled(true);\r
-            }    \r
-        } else {\r
-            timeSlider.setEnabled(false);\r
-            addAnimationButton.setEnabled(true);\r
-            insertKeyFrameButton.setEnabled(false);\r
-            removeAnimationButton.setEnabled(false);\r
-            clearKeyFrameButton.setEnabled(false);\r
-            animateButton.setEnabled(false);\r
-            animateButton.setSelection(false);\r
-            animationCombo.setEnabled(true);\r
-            usePrecalculation.setEnabled(false);\r
-            clearAnimationButton.setEnabled(false);\r
-        }\r
-    }\r
-    \r
-    private void updateKey(double k) {\r
-       key = k;\r
-       if (key >= 1.0)\r
-               key = 0.0;\r
-       else if (key < 0.0)\r
-               key = 1.0;\r
-       timeSlider.setSelection((int)(key*100.0));\r
-    }\r
-    \r
-    private class AnimateRunnable implements Runnable {\r
-        public void run() {\r
-               try {\r
-                       updateKey(key + 0.01);\r
-                       updateTime();\r
-               } catch (Exception e) {\r
-                        VisualizationScheduler.getInstance().removeVisualization(animateRunnable);\r
-               }\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void fillLocalToolBar(IToolBarManager manager) {\r
-\r
-    }\r
-    \r
-    @Override\r
-    public void fillLocalPullDown(IMenuManager manager) {\r
-       \r
-    }\r
-    \r
-    @Override\r
-    public void dispose() {\r
-       \r
-    }\r
-    \r
-    @Override\r
-    public void run() {\r
-\r
-    }\r
-\r
-}\r