From 128c7b801a83b51609522ff03e76382257e8f8d9 Mon Sep 17 00:00:00 2001 From: luukkainen Date: Mon, 29 Sep 2008 11:10:38 +0000 Subject: [PATCH] latest release (0.41), third attempt git-svn-id: https://www.simantics.org/svn/simantics/3d/trunk@6850 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../.classpath | 7 + .../.project | 28 + .../META-INF/MANIFEST.MF | 32 + .../build.properties | 5 + .../icons/difference.png | Bin 0 -> 624 bytes .../icons/difference.svg | 87 ++ .../icons/intersection.png | Bin 0 -> 622 bytes .../icons/intersection.svg | 87 ++ .../icons/link.png | Bin 0 -> 439 bytes .../icons/link.svg | 145 ++++ .../icons/union.png | Bin 0 -> 682 bytes .../icons/union.svg | 87 ++ .../icons/unlink.png | Bin 0 -> 484 bytes .../icons/unlink.svg | 126 +++ .../plugin.xml | 167 ++++ .../proconf/g3d/shapeeditor/Activator.java | 95 +++ .../g3d/shapeeditor/ShapeEditorResources.java | 48 ++ .../g3d/shapeeditor/actions/ExportAction.java | 100 +++ .../g3d/shapeeditor/actions/ImportAction.java | 81 ++ .../shapeeditor/actions/LoadFileAction.java | 62 ++ .../shapeeditor/actions/LoadFolderAction.java | 100 +++ .../common/ViewpointGenerator.java | 196 +++++ .../dialogs/PropertySelectionDialog.java | 112 +++ .../handlers/CSGProjectAdapter.java | 26 + .../shapeeditor/handlers/CSGProjectType.java | 57 ++ .../handlers/NewCSGModelHandler.java | 54 ++ .../handlers/ResourceEditorAdapter1.java | 46 ++ .../handlers/ResourceEditorAdapter3.java | 45 + .../perspectives/CSGModellingPerspective.java | 23 + .../shapeeditor/scenegraph/CSGShapeNode.java | 108 +++ .../tools/AnimationContribution.java | 774 +++++++++++++++++ .../tools/CSGModellingContribution.java | 777 ++++++++++++++++++ .../tools/ParameterizationContribution.java | 680 +++++++++++++++ .../shapeeditor/views/CSGModellingView.java | 33 + .../views/ParameterizationEditor.java | 587 +++++++++++++ .../shapeeditor/views/ShapeEditorBase.java | 628 ++++++++++++++ .../shapeeditor/views/ShapeEditorView.java | 36 + .../views/StructureOutlinePage.java | 21 + .../g3d/shapeeditor/views/StructureView.java | 44 + 39 files changed, 5504 insertions(+) create mode 100644 org.simantics.proconf.g3d.shapeeditor/.classpath create mode 100644 org.simantics.proconf.g3d.shapeeditor/.project create mode 100644 org.simantics.proconf.g3d.shapeeditor/META-INF/MANIFEST.MF create mode 100644 org.simantics.proconf.g3d.shapeeditor/build.properties create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/difference.png create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/difference.svg create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/intersection.png create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/intersection.svg create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/link.png create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/link.svg create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/union.png create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/union.svg create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/unlink.png create mode 100644 org.simantics.proconf.g3d.shapeeditor/icons/unlink.svg create mode 100644 org.simantics.proconf.g3d.shapeeditor/plugin.xml create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/Activator.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/ShapeEditorResources.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ExportAction.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ImportAction.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFileAction.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFolderAction.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/common/ViewpointGenerator.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/dialogs/PropertySelectionDialog.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectAdapter.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectType.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/NewCSGModelHandler.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter1.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter3.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/perspectives/CSGModellingPerspective.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/scenegraph/CSGShapeNode.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/AnimationContribution.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/CSGModellingContribution.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/ParameterizationContribution.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/CSGModellingView.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ParameterizationEditor.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorBase.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorView.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureOutlinePage.java create mode 100644 org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureView.java diff --git a/org.simantics.proconf.g3d.shapeeditor/.classpath b/org.simantics.proconf.g3d.shapeeditor/.classpath new file mode 100644 index 00000000..02159672 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.simantics.proconf.g3d.shapeeditor/.project b/org.simantics.proconf.g3d.shapeeditor/.project new file mode 100644 index 00000000..875413f2 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/.project @@ -0,0 +1,28 @@ + + + org.simantics.proconf.g3d.shapeeditor + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.simantics.proconf.g3d.shapeeditor/META-INF/MANIFEST.MF b/org.simantics.proconf.g3d.shapeeditor/META-INF/MANIFEST.MF new file mode 100644 index 00000000..332d852c --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/META-INF/MANIFEST.MF @@ -0,0 +1,32 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Shapeeditor Plug-in +Bundle-SymbolicName: org.simantics.proconf.g3d.shapeeditor;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: org.simantics.proconf.g3d.shapeeditor.Activator +Bundle-Vendor: VTT +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.ui.views.properties.tabbed, + com.jme.eclipse, + javax.vecmath, + org.jcae.opencascade.jni, + org.simantics.proconf.g3d, + org.simantics.image.stubs, + org.simantics.layer0.stubs, + org.simantics.layer0.utils, + org.simantics.g2d.stubs, + org.simantics.utils, + org.simantics.proconf.g3d.occ, + org.simantics.proconf.ui, + org.simantics.animation, + org.simantics.proconf.ode, + org.simantics.utils.ui, + org.simantics.equation, + org.simantics.db, + org.simantics.utils.ui.workbench, + org.simantics.proconf.browsing, + org.simantics.db.services, + org.simantics.proconf.g3d.csg +Eclipse-LazyStart: true +Export-Package: org.simantics.proconf.g3d.shapeeditor.views diff --git a/org.simantics.proconf.g3d.shapeeditor/build.properties b/org.simantics.proconf.g3d.shapeeditor/build.properties new file mode 100644 index 00000000..6f20375d --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/org.simantics.proconf.g3d.shapeeditor/icons/difference.png b/org.simantics.proconf.g3d.shapeeditor/icons/difference.png new file mode 100644 index 0000000000000000000000000000000000000000..d7b2747ee908a8610ff83131d702c08a513a6f8c GIT binary patch literal 624 zcmV-$0+0QPP)_b* zs30h46av~!-B>};f+bM9C^XPTtlAParms0Jl9#-er!x$fIrq*P=G-xm*a|FAwlTuxy?DYOo;7cVs){?e5jv&nGk5BB%A?>uubp) zBrc|e)5|_lY8IU{KcVsgw919xOD{<5&nz!?`uQP&1Uk2pzzZWEIsIyuvo|*YM5mzd zVPnYDC5RloOkX;$bw8{)W;g_-kgV#9=wOUOTiNc`ovpUAqhppsH_niBVgkS5{T%)@ z80$AZPvk-{D2NG+V9jn`--(ga1+Mnguu>6U7AQ{=ovgSJ9A7@KG9U}&mxN8=0c(P( zsG%7A$5+=a0DP7x+4AIRc>#>?Vc^P1{xpe2ue^(>bB19-lcRfA?ew_rfh0Km_zgSW zYVBB5$L{k~5C*k_9)adTo0csSjDN#_uR(yWL#5J9Rs#LPe*#ph3I7b#x`M#gplTBR zV0Lveov997S^};Cy%Gl{zPkzIbtV#{n0Np + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/org.simantics.proconf.g3d.shapeeditor/icons/intersection.png b/org.simantics.proconf.g3d.shapeeditor/icons/intersection.png new file mode 100644 index 0000000000000000000000000000000000000000..95915d3ec26701d120b906e95e691f6b25ce61ad GIT binary patch literal 622 zcmV-!0+IcRP) zbh2@%LzgUL*H*}2w zVW{L`_AwN+vD0zgZfyxKa#~{Fo`)I>Cm=n~hps4LDd4#7!Pvk-sXRIO#i0@j0ndP+fuVLrSo_*gU{&lJ z;LemlWrvd>7u47EgV`ne6(BK-ITHg8g{#yg-2bdKyGYAYs7YbQj + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/org.simantics.proconf.g3d.shapeeditor/icons/link.png b/org.simantics.proconf.g3d.shapeeditor/icons/link.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ac73c164890ed76425c4ca0ef24eac5a08b027 GIT binary patch literal 439 zcmV;o0Z9IdP)L zkiSbpVH7~mefT2-%PFECgy~j;OG84?6j4G$NJA7Mlua!WP3e$OL4QFIZc#MV=-^bl zhD3z~B}tP)gYY8X*N{=>Qxng6zI(Xe6{QsIU;&VMmQeVsj9}%1h`J!(G=Rd7uwG;B z96{rN*4n}?2Br#$p0)z3#p7keV~;cs2v##0^qd`v#wc!a)eDGH3Ynu1I|Bf_&pQ(? z-ny?H<2Ui#+KLU`t%S#1Z$~V!G5C}TW?pLo)k)C|kL^Ukut2upwA{~bdqy0(nkjZ_ zx*!i2L{kf?gn6KX;kBQZ4eQ?6zIO{@@sG{|lc`|prS1_mi0O{S`PSu0nVDvZmdds1lHD8UVl`%GaNNhJ|=Kn7)JtNBoWN+}Do~ huB@H>9{zWr5uf;^aUqO7?YjT~002ovPDHLkV1gCfy21be literal 0 HcmV?d00001 diff --git a/org.simantics.proconf.g3d.shapeeditor/icons/link.svg b/org.simantics.proconf.g3d.shapeeditor/icons/link.svg new file mode 100644 index 00000000..2ad1a0af --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/icons/link.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/org.simantics.proconf.g3d.shapeeditor/icons/union.png b/org.simantics.proconf.g3d.shapeeditor/icons/union.png new file mode 100644 index 0000000000000000000000000000000000000000..7ffeedb8be658154f8691d2ae06e4c58e7be6eb1 GIT binary patch literal 682 zcmV;b0#*HqP)NX){-$VG*LBv?cd zLPEO8jSv!%Mh^tL zfkd?S8it$T#Vng!HsEo9QbApu>uBR)^(4h!Q93H@e@yP4zRsSpT+l8_#0GfsA_Vt9 zqWOx5^_2t>OcFWYm%w}jvTi~!Q3DcH1M!bz{o+-D1UkQwzy?EaIWam%`=uQKMW3Md z{(6(GE#RoTOl{XUWi75XVBAUrT9MYm899#*FkZY8sa81{E)@y;(*IcUlk(w@xf%YS z*l&Xo3R2yxjRehY$Tf}(6Qu-@tG+=l#^vhWE5k%Vn_&h>7_=etD=$l(fDxuxwQ5tnI!)%W-u27%Nqr2c11+n{6&>_GrJYV#JpklqixJ4{u78-Zl8 zYLjghW%yCza*PVT!tfcgtYaf(lhHkp1m(l8*#AsfBSkv+6y?nze&mRg4@CNc`0R|6 z_JhN|JdeF+od8_})2w7r0=c`bA}JUi{Lwx!pBYCG8KNc9qC_JY6@~Z)0I-FisU3Q2 zpzj!D`nQ@+_y^H|N`c&Ww%ki0)auUnd&xdy*@SUuXUFlI6$2@zufQr_fmNM#X(1*Z zE8R7zQ7m^l(c~b0 + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/org.simantics.proconf.g3d.shapeeditor/icons/unlink.png b/org.simantics.proconf.g3d.shapeeditor/icons/unlink.png new file mode 100644 index 0000000000000000000000000000000000000000..5db0efc8d4b3bdf5f2f392daee85386102d8c55c GIT binary patch literal 484 zcmVL zk~=IzaTLaX=U(mgifB3*8WFFs=^!BuiLjc`m>9g;#b~WbVkVN3G$bZ5kyu15R*5Sy z2qogtNEd^6G`+ol15&+O&u{(C`JHpV98pT~9~A*eKSL-2Iga4MBBC}(d<#GkKnQi8=1+ju2h)#Y7?FZWzXAkTK69)#x~AdwVLjbv>W#j_ z0E-AZZS&WYGb@*)3m%dk=(OSCfcSmVb{Vrz#o9zqw8`fL$j3j()VoJSWKpy2ZqCzt z04=L6WqL77Hqxn3WrCbwGi?r<+n)e5ih*A0#nP;dO7-gH>9v9J=AC$z(e4-=2fECl zd6OIBsY-GDkg!P)iAe0isOY@%y6f_s-hdE-_eXLDQ<<8}+!@EcQ`M#pMUtmRDOHgT z(W!lv*3X`|j)F(Gf}G^3cm#F}13t=Tn%A4N&BF3w@Ng5HAr_E--S0yPy{*0b-uz?0 aS9$^ey@Sgo+eokg0000FxR30 literal 0 HcmV?d00001 diff --git a/org.simantics.proconf.g3d.shapeeditor/icons/unlink.svg b/org.simantics.proconf.g3d.shapeeditor/icons/unlink.svg new file mode 100644 index 00000000..ca82a54c --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/icons/unlink.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/org.simantics.proconf.g3d.shapeeditor/plugin.xml b/org.simantics.proconf.g3d.shapeeditor/plugin.xml new file mode 100644 index 00000000..e54575c4 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/plugin.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/Activator.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/Activator.java new file mode 100644 index 00000000..e256c294 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/Activator.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.management.ISessionContextChangedListener; +import org.simantics.db.management.SessionContextChangedEvent; +import org.simantics.proconf.ui.ProConfUI; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.simantics.proconf.g3d.shapeeditor"; + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + ProConfUI.getSessionContextProvider().addContextChangedListener(new ISessionContextChangedListener() { + @Override + public void sessionContextChanged(SessionContextChangedEvent event) { + ISessionContext ctx = event.getNewValue(); + if (ctx != null) { + ctx.getSession().asyncRead(new GraphRequestAdapter() { + public GraphRequestStatus perform(Graph g) throws Exception { + ShapeEditorResources.initialize(g); + return GraphRequestStatus.transactionComplete(); + }; + }); + } else { + ShapeEditorResources.deinitialize(); + } + } + }); + try { + ProConfUI.getSession().asyncRead(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + ShapeEditorResources.initialize(g); + return GraphRequestStatus.transactionComplete(); + } + }); + } catch (Exception e) { + + } + + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/ShapeEditorResources.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/ShapeEditorResources.java new file mode 100644 index 00000000..1548881c --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/ShapeEditorResources.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor; + +import org.simantics.proconf.g3d.csg.stubs.CSGResource; +import org.simantics.db.Builtins; +import org.simantics.db.Graph; +import org.simantics.equation.stubs.EquationResource; +import org.simantics.g2d.stubs.anim.AnimationResource; +import org.simantics.animation.curve.CurveBuilder; +import org.simantics.animation.curve.CurveBuilderImpl; +import org.simantics.proconf.g3d.stubs.G3DResource; + +public class ShapeEditorResources { + public static Builtins builtins; + public static G3DResource g3dResource; + public static CSGResource csgResource; + public static AnimationResource animationResource; + public static CurveBuilder curveBuilder; + public static EquationResource equationResource; + + public static void initialize(Graph g) { + builtins = g.getBuiltins(); + animationResource = AnimationResource.getInstance(g); + csgResource = CSGResource.getInstance(g); + g3dResource = G3DResource.getInstance(g); + curveBuilder = new CurveBuilderImpl(ShapeEditorResources.animationResource); + equationResource = EquationResource.getInstance(g); + } + + public static void deinitialize() { + builtins = null; + g3dResource = null; + csgResource = null; + animationResource = null; + curveBuilder = null; + equationResource = null; + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ExportAction.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ExportAction.java new file mode 100644 index 00000000..eca99896 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ExportAction.java @@ -0,0 +1,100 @@ +package org.simantics.proconf.g3d.shapeeditor.actions; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collection; + +import org.eclipse.jface.action.Action; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.layer0.utils.extent.Extent; +import org.simantics.layer0.utils.extent.ExtentUtils; +import org.simantics.layer0.utils.extent.IExtentAdvisor; +import org.simantics.layer0.utils.serialization.ConnectionPointMap; +import org.simantics.layer0.utils.serialization.TransferableGraph; +import org.simantics.layer0.utils.serialization.TransferableGraphUtils; +import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase; +import org.simantics.utils.ErrorLogger; + + +public class ExportAction extends Action{ + private ShapeEditorBase parent; + + public ExportAction(ShapeEditorBase parent) { + this.parent = parent; + this.setText("Export"); + this.setId("g3d shape export"); + } + + @Override + public void run() { + try { + doExport(); + } catch (IOException e) { + ErrorLogger.defaultLogError(e); + } + } + + private void doExport() throws IOException { + FileDialog dialog = new FileDialog(parent.getRenderingComposite().getShell(),SWT.SAVE); + String filename = dialog.open(); + if (filename == null) + return; + + final File file = new File(filename); + final FileOutputStream fos = new FileOutputStream(file); + + parent.getSession().asyncRead(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + Resource modelResource = parent.getModelResource(); + System.out.println("Exporting " + modelResource); + Collection model = ExtentUtils.determineExtent(g, new ExtentAdvisor(), modelResource); + + for (Statement s : model) + System.out.println(GraphUtils.getReadableName(g, s.getSubject())+", "+GraphUtils.getReadableName(g, s.getPredicate())+", "+GraphUtils.getReadableName(g, s.getObject())); + + ConnectionPointMap purposeProvider = new ConnectionPointMap(); + purposeProvider.put(modelResource, TransferableGraphUtils.CP_OBJECT); + + TransferableGraph dbIndependentSubgraph = TransferableGraphUtils.extractTransferableGraph(g, model, purposeProvider, null); + + byte[] data = TransferableGraphUtils.serialize(dbIndependentSubgraph); + + fos.write(data); + + System.out.println("Exporting done."); + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void requestCompleted(GraphRequestStatus status) { + try { + fos.close(); + } catch (IOException e) { + ErrorLogger.defaultLogError(e); + } + + } + }); + } + + public class ExtentAdvisor implements IExtentAdvisor { + @Override + public ExtentAdvice getAdvice(Graph g, Extent currentState, Resource extent) { + System.out.println("Extent advice : " + currentState + " : " + extent); + + //if (extent.equals(ShapeEditorResources.equationResource.Expression)) return ExtentAdvice.Include; + //return ExtentAdvice.Exclude; + return ExtentAdvice.Include; + } + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ImportAction.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ImportAction.java new file mode 100644 index 00000000..7a4d063a --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/ImportAction.java @@ -0,0 +1,81 @@ +package org.simantics.proconf.g3d.shapeeditor.actions; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import org.eclipse.jface.action.Action; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.Resource; +import org.simantics.db.Statement; +import org.simantics.layer0.utils.serialization.ConnectionPointList; +import org.simantics.layer0.utils.serialization.TransferableGraph; +import org.simantics.layer0.utils.serialization.TransferableGraphUtils; +import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase; +import org.simantics.utils.ErrorLogger; + +public class ImportAction extends Action { + + private ShapeEditorBase parent; + + public ImportAction(ShapeEditorBase parent) { + this.parent = parent; + setText("Import"); + setId("g3d shape import"); + } + + @Override + public void run() { + try { + doImport(); + } catch (IOException e) { + ErrorLogger.defaultLogError(e); + } + } + + private void doImport() throws IOException { + FileDialog dialog = new FileDialog(parent.getRenderingComposite().getShell(),SWT.OPEN); + String filename = dialog.open(); + if (filename == null) + return; + File file = new File(filename); + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + byte[] data = new byte[0]; + byte[] buf = new byte[256]; + int res = 0; + while ((res = bis.read(buf)) != -1) { + byte[] newData = new byte[data.length + res]; + System.arraycopy(data, 0, newData, 0, data.length); + System.arraycopy(buf, 0, newData, data.length, res); + data = newData; + } + bis.close(); + final byte fdata[] = data; + parent.getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + TransferableGraph sg = TransferableGraphUtils.deserialize(fdata); + ConnectionPointList purposes = TransferableGraphUtils.integrateTransferableGraph(g, sg, null); + Resource modelResource = purposes.getSingleByDescription(TransferableGraphUtils.CP_OBJECT).resource; + Resource currentModelResource = parent.getModelResource(); + for (Statement s : g.getStatements(modelResource)) { + g.removeStatements(currentModelResource, s.getPredicate()); + } + for (Statement s : g.getStatements(modelResource)) { + + g.removeStatement(s); + g.addStatement(currentModelResource, s.getPredicate(), s.getObject()); + } + + return GraphRequestStatus.transactionComplete(); + } + }); + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFileAction.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFileAction.java new file mode 100644 index 00000000..193fe45a --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFileAction.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.actions; + +import org.eclipse.jface.action.Action; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.occ.geometry.OccTriangulator; + +import com.jme.renderer.ColorRGBA; +import com.jme.scene.Geometry; +import com.jme.scene.state.MaterialState; + + +public class LoadFileAction extends Action { + private ThreeDimensionalEditorBase editor; + + public LoadFileAction(ThreeDimensionalEditorBase editor) { + super("Load file"); + this.editor = editor; + + } + + public void run() { + FileDialog loadDialog = new FileDialog(editor.getRenderingComposite().getShell(), SWT.OPEN); + String exts[] = { "*.stp;*.step", "*.iges", "*.brep", "*.ply" }; //$NON-NLS-1$ + String names[] = { "STEP (AP214/AP203)", "IGES", "BREP", "PLY" }; //$NON-NLS-1$ + loadDialog.setFilterNames(names); + loadDialog.setFilterExtensions(exts); + loadDialog.setText("Load model"); + + String filename = loadDialog.open(); + if (filename != null) { + Geometry g = OccTriangulator.getGeometryFromFile(filename)[0]; + MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState(); + ms.setAmbient(new ColorRGBA(0.f,0.f,0.f,0.f)); + ms.setEmissive(new ColorRGBA(0.f,0.f,0.f,0.f)); + ms.setShininess(128.f); + ms.setDiffuse(new ColorRGBA(0.8f,0.8f,0.8f,0.f)); + ms.setSpecular(new ColorRGBA(1.f,1.f,1.f,0.f)); + ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK); + if (g.getColorBuffer(0) != null) { + ms.setColorMaterial(MaterialState.CM_DIFFUSE); + } + g.setRenderState(ms); + editor.getRenderingComponent().getShadowRoot().attachChild(g); + // mo.setGeometry(mesh, filename); + // xithComposite.getScene().compile(); + } + + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFolderAction.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFolderAction.java new file mode 100644 index 00000000..2b7d49ec --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/actions/LoadFolderAction.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.actions; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Stack; + +import org.eclipse.jface.action.Action; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.occ.geometry.OccTriangulator; + +import com.jme.bounding.BoundingBox; +import com.jme.renderer.ColorRGBA; +import com.jme.scene.Geometry; +import com.jme.scene.state.MaterialState; + + +public class LoadFolderAction extends Action { + private ThreeDimensionalEditorBase editor; + + public LoadFolderAction(ThreeDimensionalEditorBase editor) { + super("Load folder"); + this.editor = editor; + + } + + public void run() { + + DirectoryDialog loadDialog = new DirectoryDialog(editor.getRenderingComposite().getShell(), SWT.OPEN); + loadDialog.setText("Select directory"); + + String directory = loadDialog.open(); + if (directory != null) { + File file = new File(directory); + if (!file.isDirectory()) + return; + Stack directories = new Stack(); + directories.push(file); + boolean recursive = true; + while (!directories.empty()) { + File dir = directories.pop(); + + String[] files = dir.list(new PLYFilter()); + for (String filename : files) { + Geometry g = OccTriangulator.getGeometryFromFile(dir.getAbsolutePath() + "/" + filename)[0]; + MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState(); + ms.setAmbient(new ColorRGBA(0.f,0.f,0.f,0.f)); + ms.setEmissive(new ColorRGBA(0.f,0.f,0.f,0.f)); + ms.setShininess(128.f); + ms.setDiffuse(new ColorRGBA(0.8f,0.8f,0.8f,0.f)); + ms.setSpecular(new ColorRGBA(1.f,1.f,1.f,0.f)); + ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK); + if (g.getColorBuffer(0) != null) { + ms.setColorMaterial(MaterialState.CM_DIFFUSE); + } + g.setModelBound(new BoundingBox()); + g.updateModelBound(); + g.setRenderState(ms); + editor.getRenderingComponent().getShadowRoot().attachChild(g); + g.updateWorldBound(); + g.lock(); + + } + if (recursive) { + File[] newDirs = dir.listFiles(new DirectoryFilter()); + for (File d : newDirs) + directories.push(d); + } + } + + } + + + } + + protected class DirectoryFilter implements FilenameFilter { + public boolean accept(File dir, String name) { + File file = new File(dir.getAbsolutePath() + "/" + name); + return file.isDirectory(); + } + } + + protected class PLYFilter implements FilenameFilter { + public boolean accept(File dir, String name) { + return (name.endsWith("ply")); + } + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/common/ViewpointGenerator.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/common/ViewpointGenerator.java new file mode 100644 index 00000000..68737366 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/common/ViewpointGenerator.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.common; + +import java.util.Collection; + +import org.simantics.db.Builtins; +import org.simantics.db.Resource; +import org.simantics.layer0.utils.Statement; +import org.simantics.layer0.utils.IEntity; +import org.simantics.layer0.utils.viewpoints.AcceptDecision; +import org.simantics.layer0.utils.viewpoints.AcceptRule; +import org.simantics.layer0.utils.viewpoints.PlainStateFactory; +import org.simantics.layer0.utils.viewpoints.ResourceViewpoint; +import org.simantics.layer0.utils.viewpoints.State; +import org.simantics.layer0.utils.viewpoints.StateFactory; +import org.simantics.layer0.utils.viewpoints.TraversalDecision; +import org.simantics.layer0.utils.viewpoints.TraversalRule; +import org.simantics.layer0.utils.viewpoints.rules.AcceptAllResourceAcceptRule; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; + + +public class ViewpointGenerator { + + public static ResourceViewpoint createStuctureViewpoint() { + StateFactory f = new PlainStateFactory(); + final State rootState = f.newState(); + final State projectState = f.newState(); + final State libraryState = f.newState(); + + return new ResourceViewpoint(new TraversalRule() { + @Override + public TraversalDecision makeTraversalDecision(State state, + Statement statement) { + Builtins b = statement.getGraph().getBuiltins(); + if (state.equals(rootState)) { + if (!statement.getPredicate().equals(b.ConsistsOf)) + return TraversalDecision.stopTraversal; + //if (!statement.getObject().isInstanceOf(b.Project)) + // return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(projectState); + } else if (state.equals(projectState)) { + if (!statement.getPredicate().equals(b.ConsistsOf)) + return TraversalDecision.stopTraversal; + //if (!statement.getObject().isInstanceOf(b.Library)) + // return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(libraryState); + } else if (state.equals(libraryState)) { + if (!statement.getPredicate().equals(b.ConsistsOf) + && !statement.getPredicate().isSubrelationOf( + ShapeEditorResources.g3dResource.HasChild)) + return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(libraryState); + } + return TraversalDecision.stopTraversal; + } + + @Override + public boolean areAllStatesRelevant() { + return true; + } + + @Override + public Collection relevantStates() { + return null; + } + }, new AcceptAllResourceAcceptRule(), rootState); + } + + public static ResourceViewpoint createObjectStructureViewpoint() { + StateFactory f = new PlainStateFactory(); + final State rootState = f.newState(); + + return new ResourceViewpoint(new TraversalRule() { + @Override + public TraversalDecision makeTraversalDecision(State state, + Statement statement) { + if (state.equals(rootState)) { + if (!statement.getPredicate().isSubrelationOf( + ShapeEditorResources.g3dResource.HasChild)) + return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(rootState); + } + return TraversalDecision.stopTraversal; + } + + @Override + public boolean areAllStatesRelevant() { + return true; + } + + @Override + public Collection relevantStates() { + return null; + } + }, new AcceptAllResourceAcceptRule(), rootState); + } + + public static ResourceViewpoint createObjectSizingParameterViewpoint(Resource modelToParameterRelation) { + StateFactory f = new PlainStateFactory(); + final State rootState = f.newState(); + final State endState = f.newState(); + final Resource relation = modelToParameterRelation; + + return new ResourceViewpoint(new TraversalRule() { + @Override + public TraversalDecision makeTraversalDecision(State state, + Statement statement) { + if (state.equals(rootState)) { + if (!statement.getPredicate().isSubrelationOf(relation)) + return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(endState); + } + return TraversalDecision.stopTraversal; + } + + @Override + public boolean areAllStatesRelevant() { + return true; + } + + @Override + public Collection relevantStates() { + return null; + } + }, new AcceptAllResourceAcceptRule(), rootState); + } + + public static ResourceViewpoint createViewpoint() { + StateFactory f = new PlainStateFactory(); + final State rootState = f.newState(); + final State projectState = f.newState(); + final State libraryState = f.newState(); + + return new ResourceViewpoint(new TraversalRule() { + @Override + public TraversalDecision makeTraversalDecision(State state, Statement statement) { + Builtins b = statement.getGraph().getBuiltins(); + if (state.equals(rootState)) { + if (statement.getObject().isInstanceOf(b.Ontology)) + return TraversalDecision.stopTraversal; + if(!statement.getPredicate().equals(b.ConsistsOf)) + return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(projectState); + } else if (state.equals(projectState)) { + if(!statement.getPredicate().equals(b.ConsistsOf)) + return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(libraryState); + } else if (state.equals(libraryState)) { + if(!statement.getPredicate().equals(b.ConsistsOf)) + return TraversalDecision.stopTraversal; + return TraversalDecision.continueTraversal(libraryState); + } + return TraversalDecision.stopTraversal; + } + + @Override + public boolean areAllStatesRelevant() { + return true; + } + + @Override + public Collection relevantStates() { + return null; + } + }, new AcceptRule() { + @Override + public AcceptDecision makeAcceptDecision(State state, IEntity obj) { + Builtins b = obj.getGraph().getBuiltins(); + //NOSEResource nr = NOSEResource.getInstance(obj.getGraph()); + if(obj.isInstanceOf(b.Project)) return AcceptDecision.REJECT; + else if (obj.isInstanceOf(b.Ontology)) return AcceptDecision.REJECT; + else return AcceptDecision.ACCEPT; + } + + @Override + public boolean areAllStatesRelevant() { + return true; + } + + @Override + public Collection relevantStates() { + return null; + } + }, rootState); + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/dialogs/PropertySelectionDialog.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/dialogs/PropertySelectionDialog.java new file mode 100644 index 00000000..09a5addb --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/dialogs/PropertySelectionDialog.java @@ -0,0 +1,112 @@ +package org.simantics.proconf.g3d.shapeeditor.dialogs; + +import java.util.List; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.proconf.g3d.tools.PropertyTree; + +public class PropertySelectionDialog extends Dialog { + String title = null; + String message = null; + + Session session; + PropertyTree propertyTree; + Resource[] selectedTypes = null; + List selectedPropertyInstances = null; + List selectedInstances = null; + + public PropertySelectionDialog(Shell parentShell, String dialogTitle, String dialogMessage, Session session, List selectedResources) { + super(parentShell); + this.session = session; + this.title = dialogTitle; + this.message = dialogMessage; + this.selectedInstances = selectedResources; + } + + @Override + protected void configureShell(Shell newShell) { + + super.configureShell(newShell); + if (title != null) + newShell.setText(title); + } + + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + + Label label = new Label(composite, SWT.WRAP); + label.setText(message); + GridData data = new GridData(GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL + | GridData.VERTICAL_ALIGN_CENTER); + data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); + label.setLayoutData(data); + label.setFont(parent.getFont()); + + Tree tree = new Tree(composite,SWT.SINGLE); + propertyTree = new PropertyTree(tree,session); + + GridData data2 = new GridData(GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL + | GridData.VERTICAL_ALIGN_FILL); + data2.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH); + data2.heightHint = 200; + tree.setLayoutData(data2); + tree.setFont(parent.getFont()); + + tree.showSelection(); + + applyDialogFont(composite); + + //propertyTree.setProperties(selectionAdapter.getCurrentSelection()); + propertyTree.setProperties(selectedInstances); + return composite; + } + + @Override + public boolean close() { + TreeItem selected[] = propertyTree.getTree().getSelection(); + if (selected.length == 0) { + selectedTypes = null; + } else { + selectedTypes = new Resource[selected.length]; + for (int i = 0; i < selected.length; i++) { + selectedTypes[i] = (Resource)selected[i].getData(); + } + } + //final ArrayList instances = new ArrayList(); +// for (Resource rs : selectionAdapter.getCurrentSelection().getSelectionList()) { +// instances.add(rs); +// } + + + session.syncRead(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + selectedPropertyInstances = propertyTree.findPropertyInstances(g,selectedInstances); + return GraphRequestStatus.transactionComplete(); + } + }); + + return super.close(); + } + + public List getSelectedPropertyInstances() { + return selectedPropertyInstances; + } + +} \ No newline at end of file diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectAdapter.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectAdapter.java new file mode 100644 index 00000000..5c0835d5 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectAdapter.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.handlers; + +import org.simantics.db.Graph; +import org.simantics.db.Resource; +import org.simantics.db.adaption.AdaptionException; +import org.simantics.db.adaption.ResourceAdapter; + + +public class CSGProjectAdapter implements ResourceAdapter { + @SuppressWarnings("unchecked") + @Override + public T adapt(Graph graph, Resource resource, Resource mia) throws AdaptionException { + return (T) new CSGProjectType(graph, resource); + + } +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectType.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectType.java new file mode 100644 index 00000000..a220f784 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/CSGProjectType.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.handlers; + +import java.util.ArrayList; +import java.util.Collection; + +import org.simantics.db.Builtins; +import org.simantics.db.Graph; +import org.simantics.db.Resource; +import org.simantics.layer0.utils.direct.GraphUtils; +import org.simantics.proconf.ui.projects.IProject; +import org.simantics.proconf.ui.projects.ProjectType; + +public class CSGProjectType extends ProjectType { + + public CSGProjectType(Graph graph, Resource projectTypeResource) { + super(graph, projectTypeResource); + } + + @Override + public Resource createProject(Graph g, String name) throws Exception { + Resource project = super.createProject(g, name); + Builtins b = g.getBuiltins(); + + { // Models + Resource modelLibrary = g.newResource(); + g.addStatement(modelLibrary, b.InstanceOf, b.ModelLibrary); + GraphUtils.addRelatedScalarString(g, modelLibrary, b.HasName, "Models"); + g.addStatement(project, b.ConsistsOf, modelLibrary); + } + + + + return project; + } + + @Override + public IProject loadProject(Graph g, Resource r) { + IProject project = super.loadProject(g, r); + project.set(DefaultPerspective, "org.simantics.proconf.shapeeditor.perspectives.csg"); + Collection perspectives = new ArrayList(); + perspectives.add("org.simantics.proconf.shapeeditor.perspectives.csg"); + project.set(Perspectives, perspectives); + + return project; + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/NewCSGModelHandler.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/NewCSGModelHandler.java new file mode 100644 index 00000000..be793634 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/NewCSGModelHandler.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; +import org.simantics.proconf.g3d.csg.stubs.CSGModel; + +import org.simantics.proconf.ui.ProConfUI; +import org.simantics.proconf.ui.utils.ResourceAdaptionUtils; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.Resource; +import org.simantics.layer0.stubs.Library; + + +public class NewCSGModelHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection s = HandlerUtil.getCurrentSelectionChecked(event); + IStructuredSelection ss = (IStructuredSelection) s; + if (ss.size() != 1) + return null; + final Resource lib = ResourceAdaptionUtils.toSingleResource(ss); + ProConfUI.getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + CSGModel model = CSGModel.createDefault(g); + Library l = new Library(g, lib); + l.addStatement(g.getBuiltins().ConsistsOf, model); + + return GraphRequestStatus.transactionComplete(); + } + }); + + + return null; + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter1.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter1.java new file mode 100644 index 00000000..41f07ade --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter1.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.handlers; + +import org.simantics.proconf.g3d.shapeeditor.Activator; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; +import org.simantics.proconf.ui.workbench.ResourceEditorInput; +import org.simantics.proconf.ui.workbench.editor.SimpleEditorAdapter; + +import org.simantics.db.Graph; +import org.simantics.db.Resource; +import org.simantics.utils.ui.BundleUtils; +import org.simantics.utils.ui.workbench.WorkbenchUtils; + + +public class ResourceEditorAdapter1 extends SimpleEditorAdapter { + + public ResourceEditorAdapter1() { + super("ShapeEditor", + BundleUtils.getImageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/union.png"), + null,null,null); + } + + @Override + public boolean canHandle(Graph g, Resource r) { + if(ShapeEditorResources.csgResource == null) return false; + if(ShapeEditorResources.csgResource.CSGModel == null) return false; + return g.isInstanceOf(r, ShapeEditorResources.csgResource.CSGModel); + } + + + @Override + public void openEditor(Resource r) throws Exception { + WorkbenchUtils.openEditor("org.simantics.proconf.shapeeditor.editor1", new ResourceEditorInput("org.simantics.proconf.shapeeditor.editor1",r)); + + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter3.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter3.java new file mode 100644 index 00000000..f861179e --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/handlers/ResourceEditorAdapter3.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.handlers; + +import org.simantics.db.Graph; +import org.simantics.db.Resource; +import org.simantics.proconf.g3d.shapeeditor.Activator; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; +import org.simantics.proconf.ui.workbench.ResourceEditorInput; +import org.simantics.proconf.ui.workbench.editor.SimpleEditorAdapter; +import org.simantics.utils.ui.BundleUtils; +import org.simantics.utils.ui.workbench.WorkbenchUtils; + + +public class ResourceEditorAdapter3 extends SimpleEditorAdapter { + + public ResourceEditorAdapter3() { + super("Parameterization Editor", + BundleUtils.getImageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/unlink.png"), + null,null,null); + } + + @Override + public boolean canHandle(Graph g, Resource r) { + if(ShapeEditorResources.csgResource == null) return false; + if(ShapeEditorResources.csgResource.CSGModel == null) return false; + return g.isInstanceOf(r, ShapeEditorResources.csgResource.CSGModel); + } + + + @Override + public void openEditor(Resource r) throws Exception { + WorkbenchUtils.openEditor("org.simantics.proconf.shapeeditor.editor3", new ResourceEditorInput("org.simantics.proconf.shapeeditor.editor3",r)); + + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/perspectives/CSGModellingPerspective.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/perspectives/CSGModellingPerspective.java new file mode 100644 index 00000000..f6c6a58c --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/perspectives/CSGModellingPerspective.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.perspectives; + +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +public class CSGModellingPerspective implements IPerspectiveFactory { + + @Override + public void createInitialLayout(IPageLayout layout) { + + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/scenegraph/CSGShapeNode.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/scenegraph/CSGShapeNode.java new file mode 100644 index 00000000..1bf8fe70 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/scenegraph/CSGShapeNode.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.scenegraph; + + +import org.simantics.db.Graph; +import org.simantics.db.Resource; +import org.simantics.proconf.g3d.base.GeometryProviderRegistry; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.scenegraph.IGraphicsNode; +import org.simantics.proconf.g3d.scenegraph.ShapeNode; + +import com.jme.scene.Geometry; +import com.jme.scene.state.AlphaState; +import com.jme.scene.state.ZBufferState; + + + +public class CSGShapeNode extends ShapeNode{ + + + //protected Geometry axesGeometry = null; + protected boolean axesVisible = false; + + public CSGShapeNode(ThreeDimensionalEditorBase editor,IGraphicsNode parent, Graph graph, Resource shapeResource) { + super(editor,parent, graph,shapeResource); + //axesGeometry = AxesShape.getShape(editor.getRenderingComponent().getDisplaySystem().getRenderer()); + ZBufferState zs = editor.getRenderingComponent().getDisplaySystem().getRenderer().createZBufferState(); + zs.setFunction(ZBufferState.CF_ALWAYS); + AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState(); + as.setBlendEnabled(true); + as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); + as.setSrcFunction(AlphaState.DB_SRC_ALPHA); +// axesGeometry.setRenderState(zs); +// axesGeometry.setRenderState(as); +// axesGeometry.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT); + } + + + + public Geometry[] getGeometry(Graph graph) { + + return GeometryProviderRegistry.getGeometry(getG3DNode(graph), false); + } + + public void updateAllGeometry() { + //System.out.println("CSGSHapeNode.updateAllGeometry " + shapeResource.getResourceId()); + editor.getScenegraphAdapter().updateGeometry(shapeResource); + if (parent != null && parent instanceof CSGShapeNode) { + ((CSGShapeNode)parent).updateAllGeometry(); + } + + } + + @Override + public void updateGeometry(Graph graph) { + super.updateGeometry(graph); + if (isAxesVisible()) { + //getGroup().attachChild(axesGeometry); + } else { + //axesGeometry.removeFromParent(); + } + } + + + + public boolean isAxesVisible() { + return axesVisible; + } + + public void setAxesVisible(boolean axesVisible) { + + if (this.axesVisible == axesVisible) + return; + this.axesVisible = axesVisible; + if (isAxesVisible()) { + //getGroup().getParent().attachChild(axesGeometry); + //getGroup().attachChild(axesGeometry); + } else { + //axesGeometry.removeFromParent(); + } + } + + public void setSelected(boolean selected) { + if (this.selected == selected) + return; + this.selected = selected; + if (selected) { + + setSelectedVisible(true); + setAxesVisible(true); + setTransparentVisible(true); + } else { + setSelectedVisible(false); + setAxesVisible(false); + setTransparentVisible(false); + } + } + +} 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 new file mode 100644 index 00000000..c3f7f617 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/AnimationContribution.java @@ -0,0 +1,774 @@ +package org.simantics.proconf.g3d.shapeeditor.tools; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Quat4d; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Slider; +import org.eclipse.swt.widgets.Text; +import org.simantics.db.ContextGraph; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.GraphRequestWithResult; +import org.simantics.db.Resource; +import org.simantics.g2d.stubs.anim.Animation; +import org.simantics.g2d.stubs.anim.Interpolator; +import org.simantics.g2d.stubs.anim.ScalarInterpolator; +import org.simantics.g2d.stubs.anim.SlerpInterpolator; +import org.simantics.layer0.utils.EntityFactory; +import org.simantics.layer0.utils.IEntity; +import org.simantics.layer0.utils.Property; +import org.simantics.animation.curve.SlerpCurve; +import org.simantics.animation.curve.TCBCurve; +import org.simantics.proconf.g3d.actions.ContextAction; +import org.simantics.proconf.g3d.actions.RotateAction; +import org.simantics.proconf.g3d.actions.TranslateAction; +import org.simantics.proconf.g3d.animation.Animatable; +import org.simantics.proconf.g3d.base.EditorContribution; +import org.simantics.proconf.g3d.base.G3DTools; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.base.VisualizationScheduler; +import org.simantics.proconf.g3d.common.StructuredResourceSelection; +import org.simantics.proconf.g3d.scenegraph.IGraphicsNode; +import org.simantics.proconf.g3d.scenegraph.ISelectableNode; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; +import org.simantics.proconf.g3d.shapeeditor.dialogs.PropertySelectionDialog; +import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase; +import org.simantics.proconf.g3d.stubs.G3DModel; +import org.simantics.proconf.g3d.stubs.Orientation; +import org.simantics.utils.ErrorLogger; + +public class AnimationContribution implements EditorContribution { + List actions = new ArrayList(); + + private ShapeEditorBase parent; + + private final String NO_ANIMATION = "None"; + + private Slider timeSlider; + private double key = 0; + private Composite buttonComposite; + private Button insertKeyFrameButton; + private Button clearKeyFrameButton; + private CCombo animationCombo; + private Button addAnimationButton; + private Button removeAnimationButton; + private Button clearAnimationButton; + private Button animateButton; + private Button usePrecalculation; + private Text timeText; + private Composite infoComposite; + private Text infoText; + + private Resource animationResource; + + private ContextAction translateAction; + private ContextAction rotateAction; + + public AnimationContribution(ThreeDimensionalEditorBase parent) { + this.parent = (ShapeEditorBase)parent; + } + + @Override + public String getName() { + return "Animator"; + } + + @Override + public void createControl(Composite parent) { + FormLayout flayout = new FormLayout(); + parent.setLayout(flayout); + infoComposite = new Composite(parent, SWT.BORDER); + FormData data = new FormData(); + data.top = new FormAttachment(0, 0); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.bottom = new FormAttachment(infoComposite, 0, SWT.TOP); + this.parent.getRenderingComposite().setLayoutData(data); + + infoComposite.setLayout(new FillLayout(SWT.VERTICAL)); + infoText = new Text(infoComposite, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.horizontalSpacing = 2; + layout.verticalSpacing = 2; + layout.marginWidth = 1; + layout.marginHeight = 1; + infoComposite.setLayout(layout); + GridData gdata = new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1); + // FIXME : allows text widget to take all available space (horizontal / width) + gdata.widthHint = 2000; + infoText.setLayoutData(gdata); + timeSlider = new Slider(infoComposite, SWT.NONE); + timeSlider.setValues(0, 0, 100, 1, 1, 1); + timeSlider.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + key = ((double) timeSlider.getSelection()) / 100.0; + updateTime(); + } + }); + timeSlider.setLayoutData(new GridData(SWT.FILL, 1, true, false)); + timeText = new Text(infoComposite, SWT.SINGLE); + timeText.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + updateTime(); + } + }); + timeText.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.keyCode == SWT.CR) + updateTime(); + } + }); + + buttonComposite = new Composite(infoComposite, SWT.NONE); + buttonComposite.setLayout(new FillLayout(SWT.HORIZONTAL)); + buttonComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1)); + insertKeyFrameButton = new Button(buttonComposite, SWT.PUSH); + insertKeyFrameButton.setText("Insert Keyframe"); + insertKeyFrameButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + insertKeyFrame(); + } + }); + + clearKeyFrameButton = new Button(buttonComposite, SWT.PUSH); + clearKeyFrameButton.setText("Clear Keyframe"); + + animationCombo = new CCombo(buttonComposite, SWT.NONE); + animationCombo.add(NO_ANIMATION); + animationCombo.select(0); + animationCombo.setEditable(false); + animationCombo.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + selectAnimation(); + } + }); + + addAnimationButton = new Button(buttonComposite, SWT.PUSH); + addAnimationButton.setText("New Animation"); + addAnimationButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + addAnimation(); + } + }); + + clearAnimationButton = new Button(buttonComposite, SWT.PUSH); + clearAnimationButton.setText("Clear Animation"); + clearAnimationButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + clearAnimation(); + } + }); + + removeAnimationButton = new Button(buttonComposite, SWT.PUSH); + removeAnimationButton.setText("Remove Animation"); + removeAnimationButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + removeAnimation(); + } + }); + + animateButton = new Button(buttonComposite, SWT.TOGGLE); + animateButton.setText("Animate"); + animateButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + animate(); + } + }); + + usePrecalculation = new Button(buttonComposite, SWT.CHECK); + usePrecalculation.setText("Precalc"); + + data = new FormData(); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.bottom = new FormAttachment(100, 0); + // FIXME : take account font size + data.height = 20 * 3; + infoComposite.setLayoutData(data); + + this.parent.getSelectionAdapter().addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + updateUI(); + } + }); + updateUI(); + + this.parent.getSession().asyncRead(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + G3DModel m = new G3DModel(g,AnimationContribution.this.parent.getModelResource()); + Collection animations = m.getAnimation(); + + final List animationNames = new ArrayList(); + for (Animation a : animations) { + animationNames.add(a.getName()); + } + AnimationContribution.this.parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() { + public void run() { + for (String s : animationNames) + animationCombo.add(s); + } + }); + return GraphRequestStatus.transactionComplete(); + } + + }); + } + + @Override + public void disposeControl() { + if (animateRunnable != null) + VisualizationScheduler.getInstance().removeVisualization(animateRunnable); + animateRunnable = null; + + infoComposite.dispose(); + + } + + @Override + public void fillContextMenu(Graph graph, IMenuManager manager, StructuredResourceSelection selection) { + + } + + + + @Override + public Collection getActions() { + return actions; + } + + @Override + public void initialize(Graph graph) { + actions.add(translateAction = new TranslateAction(parent) { + @Override + public void setInfoText(String text) { + infoText.setText(text); + } + }); + actions.add(rotateAction = new RotateAction(parent){ + @Override + public void setInfoText(String text) { + infoText.setText(text); + } + }); + } + + private double getCurrentKey() { + return key; + } + + private void updateTime() { + final double t = getCurrentKey(); + timeText.setText(Double.toString(t)); + if (animationResource == null) + return; + if (usePrecalculation.getSelection()) { + for (IGraphicsNode n : parent.getScenegraphAdapter().getNodes()) { + if (n instanceof Animatable) { + // TODO : frame-rate dependent animations + ((Animatable)n).animate(t,0.0); + } + parent.setViewChanged(true); + } + } else { + parent.getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + Collection interpolators = getAnimation(g).getRelatedObjects(ShapeEditorResources.animationResource.HasInterpolator); + for (IEntity i : interpolators) { + if (i.isInstanceOf(ShapeEditorResources.animationResource.ScalarInterpolator)) { + // TODO : creating curve each time when time is set is + // slow. Curve should be cached + TCBCurve c = (TCBCurve) ShapeEditorResources.curveBuilder.loadInterpolator(i); + double out = c.evaluate(t); + g.setScalarDouble(i.getSingleRelatedObject(ShapeEditorResources.animationResource.HasTarget).getResource(), out); + } else if (i.isInstanceOf(ShapeEditorResources.animationResource.SlerpInterpolator)) { + // TODO : creating curve each time when time is set is slow. + // Curve should be cached + SlerpCurve c = (SlerpCurve) ShapeEditorResources.curveBuilder.loadInterpolator(i); + Quat4d out = c.evaluate(t); + Orientation r = new Orientation(i.getSingleRelatedObject(ShapeEditorResources.animationResource.HasTarget)); + AxisAngle4d aa = new AxisAngle4d(); + aa.set(out); + G3DTools.setOrientation(r, aa); + } + } + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void requestCompleted(GraphRequestStatus status) { + parent.getScenegraphAdapter().setChanged(true); + } + }); + } + } + + private IEntity findPropertyInterpolator(Graph g, Resource property) { + Collection interpolators = getAnimation(g).getRelatedObjects(ShapeEditorResources.animationResource.HasInterpolator); + for (IEntity i : interpolators) { + IEntity e = i.getAtMostOneRelatedObject(ShapeEditorResources.animationResource.HasTarget); + if (e == null) + continue; + if (e.getResource().equals(property)) { + return i; + } + } + return null; + } + + private void insertKeyFrame() { + ArrayList instances = new ArrayList(); + for (Resource rs : parent.getSelectionAdapter().getCurrentSelection().getSelectionList()) { + instances.add(rs); + } + PropertySelectionDialog dialog = new PropertySelectionDialog(parent.getRenderingComposite().getShell(),"Select property","Select animated property",parent.getSession(),instances); + if (dialog.open() == Dialog.CANCEL) { + return; + } + final List properties = dialog.getSelectedPropertyInstances(); + parent.getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + for (Resource r : properties) { + IEntity t = EntityFactory.create(g,r); + IEntity current = findPropertyInterpolator(g, r); + if (t.isInstanceOf(ShapeEditorResources.g3dResource.Position)) { + + for (int i = 0; i < 3; i++) { + IEntity d = null; + switch (i) { + case 0: + d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasX); + break; + case 1: + d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasY); + break; + case 2: + d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasZ); + break; + } + current = findPropertyInterpolator(g, d.getResource()); + addScalarKey(current,d); + } + + } else if (t.isInstanceOf(ShapeEditorResources.g3dResource.Orientation)) { + Orientation rot = new Orientation(t); + addSlerpKey(current, rot); + } else if (t.isInstanceOf(ShapeEditorResources.g3dResource.Color)) { + for (int i = 0; i < 3; i++) { + IEntity d = null; + switch (i) { + case 0: + d = t.getSingleRelatedObject(ShapeEditorResources.g3dResource.HasRed); + break; + case 1: + break; + case 2: + break; + } + current = findPropertyInterpolator(g, d.getResource()); + addScalarKey(current,d); + } + } else if (t.isInstanceOf(g.getBuiltins().Double)) { + addScalarKey(current,t); + } else { + // TODO: basic cases are handled, only way to support + // is to find all doubles from property structure and + // interpolators attached to them, if there's any + ErrorLogger.getDefault().logWarning("Default keyframe adding has not been implemented", null); + } + } + return GraphRequestStatus.transactionComplete(); + } + }); + } + + private void addScalarKey(IEntity current, IEntity d) { + + Graph graph = d.getGraph(); + if (current == null) { + current = ScalarInterpolator.createDefault(graph).toInterpolator(); // FIXME : stubcast + getAnimation(graph).addStatement(ShapeEditorResources.animationResource.HasInterpolator, current); + current.addStatement(ShapeEditorResources.animationResource.HasTarget, d); + } + ShapeEditorResources.curveBuilder.addKey(current,getCurrentKey(),new double[]{d.getGraph().getScalarDouble(d.getResource()),0.0,0.0,0.0}); + } + + private void addSlerpKey(IEntity current, Orientation r) { + Graph graph = r.getGraph(); + if (current == null) { + current = SlerpInterpolator.createDefault(graph).toInterpolator(); // FIXME : stubcast + getAnimation(graph).addStatement(ShapeEditorResources.animationResource.HasInterpolator, current); + current.addStatement(ShapeEditorResources.animationResource.HasTarget, r); + + } + AxisAngle4d aa = G3DTools.getOrientation(r); + Quat4d q = new Quat4d(); + q.set(aa); + ShapeEditorResources.curveBuilder.addKey(current,getCurrentKey(),new double[]{q.w,q.x,q.y,q.z}); + } + + private void selectAnimation() { + if (animationCombo.getSelectionIndex() == 0) { + animationResource = null; + updateUI(); + } else { + final String name = animationCombo.getItem(animationCombo.getSelectionIndex()); + parent.getSession().asyncRead(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + + Resource modelResource = parent.getModelResource(); + G3DModel m = new G3DModel(g, modelResource); + Collection animations = m.getAnimation(); + boolean found = false; + for (Animation a : animations) { + if (a.getName().startsWith(name) && a.getName().length() == name.length()) { + animationResource = a.getResource(); + found = true; + break; + } + } + if (!found) { + ErrorLogger.defaultLogError("Could find animation " + name + " for model " + m.getResource(), null); + animationResource = null; + } + return GraphRequestStatus.transactionComplete(); + } + @Override + public void requestCompleted(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + updateUI(); + } + }); + } + }); + } + } + + private Animation getAnimation(Graph graph) { + return new Animation(graph, animationResource); + } + + private void addAnimation() { + InputDialog d = new InputDialog(parent.getRenderingComposite().getShell(),"Animation name","Animation name","",null); + if (d.open() == InputDialog.CANCEL) { + return; + } + final String name = d.getValue(); + if (name == null || name.length() == 0) { + return; + } + parent.getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + G3DModel m = parent.getModel(g); + Collection animations = m.getRelatedObjects(ShapeEditorResources.animationResource.HasAnimation); + for (IEntity a : animations) { + if (a.getName().startsWith(name) && a.getName().length() == name.length()) { + ErrorLogger.getDefault().logWarning("Cannot add animation with the same name " + name, null); + return GraphRequestStatus.transactionCancel(); + } + } + + Animation newAnimation = Animation.createDefault(g); + newAnimation.setName(name); + m.addStatement(ShapeEditorResources.animationResource.HasAnimation, newAnimation); + + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void requestCompleted(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() { + public void run() { + animationCombo.add(name); + animationCombo.select(animationCombo.indexOf(name)); + selectAnimation(); + } + }); + } + }); + } + + private void removeAnimation() { + assert(animationResource != null); + GraphRequestWithResult r = new GraphRequestWithResult() { + public String performWithResult(Graph g) throws Exception { + return getAnimation(g).getName(); + }; + }; + parent.getSession().syncRead(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); + if (dialog.open() == 1) + return; + parent.getSession().asyncWrite(new GraphRequestAdapter() { + String name; + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + + Animation currentAnimation = getAnimation(g); + name = currentAnimation.getName(); + parent.getModel(g).removeStatement(ShapeEditorResources.animationResource.HasAnimation, currentAnimation); + + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void requestCompleted(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() { + public void run() { + animationCombo.remove(animationCombo.indexOf(name)); + } + }); + } + }); + } + + private void clearAnimation() { + assert(animationResource != null); + + parent.getSession().asyncWrite(new GraphRequestAdapter() { + + boolean proceed; + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + int size = getAnimation(g).getInterpolator().size(); + if (size == 0) + return GraphRequestStatus.transactionCancel(); + final String name = getAnimation(g).getName(); + parent.getRenderingComposite().getDisplay().syncExec(new Runnable() { + public void run() { + MessageDialog dialog = new MessageDialog(parent.getRenderingComposite().getShell(),"Confirm",null,"Do you want to clear animation " + name ,MessageDialog.QUESTION,new String[]{"Yes","No"},1); + proceed = (dialog.open() != MessageDialog.CANCEL); + } + }); + if (proceed) { + //getAnimation(g).getInterpolator().clear(); + getAnimation(g).removeRelatedStatements(ShapeEditorResources.animationResource.HasInterpolator); + return GraphRequestStatus.transactionComplete(); + } else { + return GraphRequestStatus.transactionCancel(); + } + } + }); + } + + public Graph createAnimationParameterization(Graph g) { + if (g.getObjects(parent.getModelResource(), ShapeEditorResources.g3dResource.HasSizingParameter).size() > 0) { + ContextGraph graph; + if (!(g instanceof ContextGraph)) { + graph = new ContextGraph(g); + graph.setContext(parent.getModelResource()); + } else { + graph = (ContextGraph)g; + } + Animation animation = getAnimation(graph); + Collection interpolators = animation.getInterpolator(); + for (org.simantics.g2d.stubs.anim.Interpolator interpolator : interpolators) { + IEntity target = interpolator.getTarget(); + // check all model properties + G3DModel model = parent.getModel(graph); + Collection modelProperties = model.getRelatedProperties(ShapeEditorResources.g3dResource.HasSizingParameter); + for (Property p : modelProperties) { + IEntity t = EntityFactory.create(graph,p.getResource()); + // get parameterization equations + Collection equations = t.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget); + // get parameterized values + Collection parameterTargets = new ArrayList(); + for (IEntity eq : equations) { + Collection tgts = eq.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget); + assert(tgts.size() == 1); + parameterTargets.add(tgts.iterator().next()); + } + // do matching between interpolator targets and parameterized values + // TODO : old system did not have inverse relations but current system does. + // it is possible to take interpolation target and find if it is connected to an equation + // this would make code much faster (no more stupid loops over everything) + for (IEntity d : parameterTargets) { + if (d.getResource().equals(target.getResource())) { + // get default value for sizing property + Collection prop = t.getRelatedObjects(ShapeEditorResources.g3dResource.HasDefaultDoubleValue); + if (prop.size() == 1) { + ShapeEditorResources.curveBuilder.parameterize(interpolator, prop.iterator().next().toProperty().getDoubleArray(), p.getDoubleArray()); + } else { + ErrorLogger.defaultLogError("Cannot parameterize interpolator " + interpolator.getResource() + " of animation " + animation.getResource() + " since parameter " + p.getResource() + " has no default value", null); + } + } + } + } + } + + return graph; + } else { + return g; + } + } + + private AnimateRunnable animateRunnable = null; + + private void animate() { + updateUI(); + if (animateButton.getSelection()) { + if (animateRunnable != null) + return; + if (usePrecalculation.getSelection()) { + parent.getSession().asyncRead(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + Graph graph = parent.createParameterization(g); + createAnimationParameterization(graph); + for (IGraphicsNode n : parent.getScenegraphAdapter().getNodes()) { + if (n instanceof ISelectableNode) { + if (!((ISelectableNode)n).isVisible()) + continue; + } + if (n instanceof Animatable) { + ((Animatable)n).setAnimation(graph,animationResource); + } + } + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void requestCompleted(GraphRequestStatus status) { + animateRunnable = new AnimateRunnable(); + VisualizationScheduler.getInstance().addVisualization(animateRunnable); + } + }); + } else { + animateRunnable = new AnimateRunnable(); + VisualizationScheduler.getInstance().addVisualization(animateRunnable); + } + + } else { + if (animateRunnable == null) + return; + VisualizationScheduler.getInstance().removeVisualization(animateRunnable); + animateRunnable = null; + if (usePrecalculation.getSelection()) { + // updateTime updates values to graph if precalculation is not used. + // we must store current values from animation to synchronize view and graph + // information so that use can modify animation properly. + usePrecalculation.setSelection(false); + updateTime(); + usePrecalculation.setSelection(true); + for (IGraphicsNode n : parent.getScenegraphAdapter().getNodes()) { + if (n instanceof Animatable) { + ((Animatable)n).setAnimation(null,null); + } + } + } + } + } + + private void updateUI() { + if (animationResource != null) { + animateButton.setEnabled(true); + timeSlider.setEnabled(true); + if (animateButton.getSelection()) { + addAnimationButton.setEnabled(false); + insertKeyFrameButton.setEnabled(false); + removeAnimationButton.setEnabled(false); + clearKeyFrameButton.setEnabled(false); + animationCombo.setEnabled(false); + usePrecalculation.setEnabled(false); + clearAnimationButton.setEnabled(false); + } else { + addAnimationButton.setEnabled(true); + insertKeyFrameButton.setEnabled(!parent.getSelectionAdapter().getCurrentSelection().isEmpty()); + removeAnimationButton.setEnabled(true); + clearKeyFrameButton.setEnabled(false); //FIXME : detect keyframes + animationCombo.setEnabled(true); + usePrecalculation.setEnabled(true); + clearAnimationButton.setEnabled(true); + } + } else { + timeSlider.setEnabled(false); + addAnimationButton.setEnabled(true); + insertKeyFrameButton.setEnabled(false); + removeAnimationButton.setEnabled(false); + clearKeyFrameButton.setEnabled(false); + animateButton.setEnabled(false); + animateButton.setSelection(false); + animationCombo.setEnabled(true); + usePrecalculation.setEnabled(false); + clearAnimationButton.setEnabled(false); + } + } + + private void updateKey(double k) { + key = k; + if (key >= 1.0) + key = 0.0; + else if (key < 0.0) + key = 1.0; + timeSlider.setSelection((int)(key*100.0)); + } + + private class AnimateRunnable implements Runnable { + public void run() { + try { + updateKey(key + 0.01); + updateTime(); + } catch (Exception e) { + VisualizationScheduler.getInstance().removeVisualization(animateRunnable); + } + } + } + + @Override + public void fillLocalToolBar(IToolBarManager manager) { + + } + + @Override + public void fillLocalPullDown(IMenuManager manager) { + + } + + @Override + public void dispose() { + + } + + @Override + public void run() { + + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/CSGModellingContribution.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/CSGModellingContribution.java new file mode 100644 index 00000000..dd80c96b --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/CSGModellingContribution.java @@ -0,0 +1,777 @@ +package org.simantics.proconf.g3d.shapeeditor.tools; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; +import java.util.Map.Entry; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Point3d; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.Resource; +import org.simantics.layer0.stubs.Property; +import org.simantics.layer0.utils.EntityFactory; +import org.simantics.layer0.utils.IEntity; +import org.simantics.layer0.utils.instantiation.Instance; +import org.simantics.layer0.utils.instantiation.InstanceFactory; +import org.simantics.proconf.g3d.actions.ContextAction; +import org.simantics.proconf.g3d.actions.FocusAction; +import org.simantics.proconf.g3d.actions.RemoveAction; +import org.simantics.proconf.g3d.actions.RotateAction; +import org.simantics.proconf.g3d.actions.TranslateAction; +import org.simantics.proconf.g3d.actions.WriteAction; +import org.simantics.proconf.g3d.base.EditorContribution; +import org.simantics.proconf.g3d.base.G3DAPI; +import org.simantics.proconf.g3d.base.G3DTools; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.common.StructuredResourceSelection; +import org.simantics.proconf.g3d.csg.stubs.BooleanOperation; +import org.simantics.proconf.g3d.csg.stubs.CSGModel; +import org.simantics.proconf.g3d.csg.stubs.CSGShape; +import org.simantics.proconf.g3d.csg.stubs.Difference; +import org.simantics.proconf.g3d.csg.stubs.Intersection; +import org.simantics.proconf.g3d.csg.stubs.Primitive; +import org.simantics.proconf.g3d.csg.stubs.Union; +import org.simantics.proconf.g3d.scenegraph.IGraphicsNode; +import org.simantics.proconf.g3d.shapeeditor.Activator; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; +import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase; +import org.simantics.proconf.g3d.stubs.G3DNode; +import org.simantics.proconf.g3d.stubs.Shape; +import org.simantics.utils.ErrorLogger; + +public class CSGModellingContribution implements EditorContribution { + + private static ImageDescriptor INTERSECTION_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID,"icons/intersection.png"); + private static ImageDescriptor UNION_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/union.png"); + private static ImageDescriptor DIFFERENCE_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID,"icons/difference.png"); + + private ShapeEditorBase parent; + + private List actions = new ArrayList(); + + private List addActions = new ArrayList(); + private ContextAction unionAction; + private ContextAction differenceAction; + private ContextAction intersectionAction; + private ContextAction splitAction; + private ContextAction linkAction; + private ContextAction unlinkAction; + private ContextAction translateAction; + private ContextAction rotateAction; + private ContextAction removeAction; + + private Composite infoComposite; + private Text infoText; + + + public CSGModellingContribution(ThreeDimensionalEditorBase parent) { + this.parent = (ShapeEditorBase)parent; + } + + @Override + public String getName() { + return "Shape Editing"; + } + + @Override + public void initialize(Graph graph) { + makeActions(graph); + } + + @Override + public void createControl(Composite parent) { + FormLayout flayout = new FormLayout(); + parent.setLayout(flayout); + infoComposite = new Composite(parent, SWT.BORDER); + FormData data = new FormData(); + data.top = new FormAttachment(0, 0); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.bottom = new FormAttachment(infoComposite, 0, SWT.TOP); + this.parent.getRenderingComposite().setLayoutData(data); + data = new FormData(); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.bottom = new FormAttachment(100, 0); + data.height = 18; + infoComposite.setLayoutData(data); + GridLayout layout = new GridLayout(1,false); + layout.marginWidth = 1; + layout.marginHeight = 1; + infoComposite.setLayout(layout); + infoText = new Text(infoComposite, SWT.NONE); + GridData gdata = new GridData(); + gdata.grabExcessHorizontalSpace = true; + gdata.horizontalAlignment = SWT.FILL; + infoText.setLayoutData(gdata); + } + + @Override + public void disposeControl() { + infoComposite.dispose(); + } + + @Override + public void fillContextMenu(Graph graph, IMenuManager manager, StructuredResourceSelection selection) { + + if (selection.isEmpty()) { + MenuManager addMenu = new MenuManager("Add", "add"); + addMenu.setRemoveAllWhenShown(false); + for (Action a : addActions) { + addMenu.add(a); + } + manager.add(addMenu); + } + + } + + protected void makeActions(Graph graph) { + actions.add(translateAction = new TranslateAction(parent) { + @Override + public void setInfoText(String text) { + infoText.setText(text); + } + }); + actions.add(rotateAction = new RotateAction(parent){ + @Override + public void setInfoText(String text) { + infoText.setText(text); + } + }); + actions.add(removeAction = new RemoveAction(parent)); + actions.add(new FocusAction(parent)); + + + IEntity primitive = EntityFactory.create(graph,ShapeEditorResources.csgResource.Primitive); + + Collection primitives = primitive.getRelatedObjects(graph.getBuiltins().SupertypeOf); + + TreeMap sorter = new TreeMap(); + for (IEntity p : primitives) { + String key = p.getName(); + if (key.equals("")) + key = "ERROR (" + p.getURI() + ")"; + sorter.put(key, p.getResource()); + } + + for (Entry e : sorter.entrySet()) { + final String name = e.getKey(); + final Resource r = e.getValue(); + Action a = new Action() { + Resource res; + public void run() { + parent.getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + + Instance ins = InstanceFactory.getInstanceOfType(g,r); + Resource instance = ins.instantiate(g); + Shape shape = new Shape(g,instance); + res = shape.getResource(); + resetShape(shape); + CSGModel model = new CSGModel(g,parent.getModelResource()); + model.addStatement(ShapeEditorResources.g3dResource.HasChild, shape.getResource()); + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void handleException(Throwable e) { + super.handleException(e); + ErrorLogger.defaultLogError("Adding " + name + " failed.", e); + } + + @Override + public void requestCompleted(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){ + public void run() { + parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(res)); + } + }); + } + }); + } + }; + a.setText(name); + a.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); + addActions.add(a); + + } + + unionAction = new WriteAction(parent,false) { + + Resource r; + @Override + public boolean usable(Graph graph,List resources) { + if (resources.size() >= 2) + return true; + return false; + } + + public GraphRequestStatus doChanges(Graph graph) { + List list = parent.getSelectionAdapter().getSelectedObjects(); + if (list.size() < 2) { + showMessage("Union works between two objects"); + return GraphRequestStatus.transactionCancel(); + } + Resource r1 = list.get(0).getResource(); + CSGShape shape1 = new CSGShape(graph,r1); + + G3DNode parent = shape1.getParent(); + if (parent == null) { + showMessage("Primary shape has no parent, don't know what to do"); + return GraphRequestStatus.transactionCancel(); + } + BooleanOperation op = Union.createDefault(graph).toBooleanOperation(); //FIXME : stubcast + r = op.getResource(); + if (createBooleanOp(op, parent, shape1, list)) + return GraphRequestStatus.transactionComplete(); + else + return GraphRequestStatus.transactionCancel(); + } + + @Override + public void afterChanges(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){ + public void run() { + parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r)); + } + }); + } + }; + unionAction.setText("Union"); + unionAction.setToolTipText("Union"); + unionAction.setImageDescriptor(UNION_IMAGE); + + differenceAction = new WriteAction(parent,false) { + + Resource r; + @Override + public boolean usable(Graph graph,List resources) { + if (resources.size() >= 2) + return true; + return false; + } + + public GraphRequestStatus doChanges(Graph graph) { + List list = parent.getSelectionAdapter().getSelectedObjects(); + if (list.size() < 2) { + showMessage("Difference works between two objects"); + return GraphRequestStatus.transactionCancel(); + } + CSGShape shape1 = new CSGShape(graph,list.get(0).getResource()); + G3DNode parent = shape1.getParent(); + if (parent == null) { + showMessage("Primary shape has no parent, don't know what to do"); + return GraphRequestStatus.transactionCancel(); + } + BooleanOperation op = Difference.createDefault(graph).toBooleanOperation(); //FIXME : stubcast + r = op.getResource(); + if (createBooleanOp(op, parent, shape1, list)) + return GraphRequestStatus.transactionComplete(); + else + return GraphRequestStatus.transactionCancel(); + } + + @Override + public void afterChanges(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){ + public void run() { + parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r)); + } + }); + } + }; + differenceAction.setText("Difference"); + differenceAction.setToolTipText("Difference"); + differenceAction.setImageDescriptor(DIFFERENCE_IMAGE); + + intersectionAction = new WriteAction(parent,false) { + Resource r; + @Override + public boolean usable(Graph graph,List resources) { + if (resources.size() >= 2) + return true; + return false; + } + + public GraphRequestStatus doChanges(Graph graph) { + List list = parent.getSelectionAdapter() + .getSelectedObjects(); + if (list.size() < 2) { + showMessage("Intersection works between two objects"); + return GraphRequestStatus.transactionCancel(); + } + CSGShape shape1 = new CSGShape(graph,list.get(0).getResource()); + G3DNode parent = shape1.getParent(); + if (parent == null) { + showMessage("Primary shape has no parent, don't know what to do"); + return GraphRequestStatus.transactionCancel(); + } + BooleanOperation op = Intersection.createDefault(graph).toBooleanOperation(); //FIXME : stubcast + r = op.getResource(); + if (createBooleanOp(op, parent, shape1, list)) + return GraphRequestStatus.transactionComplete(); + else + return GraphRequestStatus.transactionCancel(); + } + + @Override + public void afterChanges(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){ + public void run() { + parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r)); + } + }); + + } + }; + intersectionAction.setText("Intersection"); + intersectionAction.setToolTipText("Intersection"); + intersectionAction.setImageDescriptor(INTERSECTION_IMAGE); + + splitAction = new WriteAction(parent,false) { + + @Override + public boolean usable(Graph graph,List resources) { + if (resources.size() == 1) { + Resource r = resources.iterator().next(); + IEntity t = EntityFactory.create(graph,r); + if (t.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) { + return true; + } + } + + return false; + } + + + + public GraphRequestStatus doChanges(Graph graph) { + List list = parent.getSelectionAdapter().getSelectedObjects(); + if (list.size() != 1) { + showMessage("Split requires one object"); + return GraphRequestStatus.transactionCancel(); + } + Resource deletedResource = list.get(0).getResource(); + IEntity deletedEntity = EntityFactory.create(graph,deletedResource); + if (!deletedEntity.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) { + showMessage("Split requires boolean operation"); + return GraphRequestStatus.transactionCancel(); + } + Collection parents = deletedEntity.getRelatedObjects(ShapeEditorResources.g3dResource.HasParent); + if (parents.size() != 1) { + showMessage("Shape has " + parents.size() + + " parents, don't know what to do"); + return GraphRequestStatus.transactionCancel(); + } + IEntity parent = parents.iterator().next(); + // find all shapes and their positions and orientations relative to world coordinates + BooleanOperation op = new BooleanOperation(deletedEntity); + CSGShape shape1 = op.getMainShape(); + Point3d shape1WorldPos = G3DTools.getPoint(shape1.getWorldPosition()); + AxisAngle4d shape1WorldRot = G3DTools.getOrientation(shape1.getWorldOrientation()); + //System.out.println(shape1WorldPos + " " + shape1WorldRot); + Collection shape2s = op.getSecondaryShape(); + + ArrayList shape2WorldPos = new ArrayList(); + ArrayList shape2WorldRot = new ArrayList(); + for (CSGShape shape : shape2s) { + Point3d pos = G3DTools.getPoint(shape.getWorldPosition()); + AxisAngle4d rot = G3DTools.getOrientation(shape.getWorldOrientation()); + shape2WorldPos.add(pos); + shape2WorldRot.add(rot); + //System.out.println(pos + " " + rot); + } + + // removed boolean operation is either connected to model or another boolean operation. + CSGModel m = new CSGModel(graph,CSGModellingContribution.this.parent.getModelResource()); + if (parent.getResource().equals(CSGModellingContribution.this.parent.getModelResource())) { + // if deleted boolean operation is connected to the model, + // all its children are added to the model + + m.removeStatement(ShapeEditorResources.g3dResource.HasChild, op); + m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape1); + for (CSGShape shape2 : shape2s) { + m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2); + } + + } else { + // deleted boolean operation is connected to another boolean + // operation + // if the deleted boolean operation is primary child, we'll + // must replace it with deleted boolean operations + // primary child + if (!parent.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) { + ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!", null); + return GraphRequestStatus.transactionCancel(); + } + BooleanOperation parentOp = new BooleanOperation(parent); + // we'll have to list all secondary shapes in parent boolean + // op so that we can find the correct relatio + Collection parentShape2s = parentOp.getRelatedObjects(ShapeEditorResources.csgResource.HasSecondaryShape); + + if (parentOp.getMainShape().getResource().equals(deletedResource)) { + // split boolean operation is the primary child in the + // parent boolean operation + parent.removeStatement(ShapeEditorResources.csgResource.HasMainShape,deletedResource); + // graph.commitChanges(ShapeEditorView.this); + parent.addStatement(ShapeEditorResources.csgResource.HasMainShape, shape1); + // graph.commitChanges(ShapeEditorView.this); + for (CSGShape shape2 : shape2s) { + m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2); + } + } else if (contains(parentShape2s, deletedResource)) { + // split boolean operation is one of the secondary + // shapes in the parent boolean operation + parent.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape,deletedResource); + // graph.commitChanges(ShapeEditorView.this); + parent.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape,shape1); + // graph.commitChanges(ShapeEditorView.this); + + // model.getConsistOfShapeSet().add(shape2); + for (CSGShape shape2 : shape2s) { + m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2); + } + } else { + ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!", null); + return GraphRequestStatus.transactionCancel(); + } + } + deletedEntity.removeStatement(ShapeEditorResources.csgResource.HasMainShape, shape1); + for (CSGShape shape2 : shape2s) + deletedEntity.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape, shape2); + //graph.commit(); + //System.out.println("Setting original transformations"); + //G3DTools.setTuple3(shape1.getWorldPosition(), shape1WorldPos); + //G3DTools.setOrientation(shape1.getWorldOrientation(), shape1WorldRot); + G3DAPI.setWorldTransformation(shape1, shape1WorldPos,shape1WorldRot); + + int i = 0; + for (CSGShape shape : shape2s) { + G3DAPI.setWorldTransformation(shape, shape2WorldPos.get(i),shape2WorldRot.get(i)); + //G3DTools.setTuple3(shape.getWorldPosition(), shape2WorldPos.get(i)); + //G3DTools.setOrientation(shape.getWorldOrientation(),shape2WorldRot.get(i)); + i++; + } + return GraphRequestStatus.transactionComplete(); + + } + }; + splitAction.setText("Split"); + splitAction.setToolTipText("Split"); + splitAction.setImageDescriptor(PlatformUI.getWorkbench() + .getSharedImages().getImageDescriptor( + ISharedImages.IMG_OBJS_INFO_TSK)); + + linkAction = new WriteAction(parent,false) { + Resource r; + @Override + public boolean usable(Graph graph,List resources) { + if (resources.size() == 2) { + Iterator i = resources.iterator(); + Shape s1 = new Shape(graph,i.next()); + Shape s2 = new Shape(graph,i.next()); + if (s1.getRelatedObjects(ShapeEditorResources.g3dResource.GeometryDefinitionOf).size() == 0 && + s2.getRelatedObjects(ShapeEditorResources.g3dResource.GeometryDefinitionOf).size() == 0) + return true; + + } + return false; + } + + public GraphRequestStatus doChanges(Graph graph) { + List list = parent.getSelectionAdapter().getSelectedObjects(); + if (list.size() != 2) { + showMessage("Link works between two objects"); + return GraphRequestStatus.transactionCancel(); + } + Resource r1 = list.get(0).getResource(); + Resource r2 = list.get(1).getResource(); + + CSGShape shape1 = new CSGShape(graph,r1); + CSGShape shape2 = new CSGShape(graph,r2); + + Point3d p = G3DTools.getPoint(shape2.getWorldPosition()); + AxisAngle4d aa = G3DTools.getOrientation(shape2.getWorldOrientation()); + //System.out.println(p + " " + aa); + shape2.removeRelatedStatements(ShapeEditorResources.g3dResource.HasParent); + r = shape2.getResource(); + //System.out.println("Link remove commit"); + //graph.commitChanges(ShapeEditorView.this); + //shape1.getChild().add(shape2.toG3DNode()); //FIXME : stubcast + shape1.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2); + // FIXME : this is needed + //System.out.println("Link add commit"); + //graph.commitChanges(ShapeEditorView.this); + //G3DTools.setTuple3(shape2.getWorldPosition(), p); + //G3DTools.setOrientation(shape2.getWorldOrientation(), aa); + G3DAPI.setWorldTransformation(shape2, p, aa); + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void afterChanges(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){ + public void run() { + parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r)); + } + }); + } + }; + linkAction.setText("Link"); + linkAction.setToolTipText("Link"); + linkAction.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/link.png")); + + unlinkAction = new WriteAction(parent,false) { + Resource r; + @Override + public boolean usable(Graph graph,List resources) { + if (resources.size() == 1) { + Iterator i = resources.iterator(); + Shape s1 = new Shape(graph,i.next()); + return (s1.getRelatedObjects(ShapeEditorResources.g3dResource.GeometryDefinitionOf).size() == 0 + && s1.getParent() != null && !s1.getParent() + .getResource().equals(CSGModellingContribution.this.parent.getModelResource())); + + } + return false; + } + + public GraphRequestStatus doChanges(Graph graph) { + List list = parent.getSelectionAdapter().getSelectedObjects(); + if (list.size() != 1) { + showMessage("Unlink works with one object"); + return GraphRequestStatus.transactionCancel(); + } + Resource r1 = list.get(0).getResource(); + + CSGShape shape1 = new CSGShape(graph,r1); + CSGModel m = new CSGModel(graph,CSGModellingContribution.this.parent.getModelResource()); + Point3d p = G3DTools.getPoint(shape1.getWorldPosition()); + AxisAngle4d aa = G3DTools.getOrientation(shape1.getWorldOrientation()); + shape1.removeRelatedStatements(ShapeEditorResources.g3dResource.HasParent); + //graph.commitChanges(ShapeEditorView.this); + m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape1); + // FIXME : this is needed + //graph.commitChanges(ShapeEditorView.this); + //G3DTools.setTuple3(shape1.getWorldPosition(), p); + //G3DTools.setOrientation(shape1.getWorldOrientation(), aa); + G3DAPI.setWorldTransformation(shape1, p, aa); + r = shape1.getResource(); + return GraphRequestStatus.transactionComplete(); + } + + @Override + public void afterChanges(GraphRequestStatus status) { + parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){ + public void run() { + parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r)); + } + }); + } + }; + unlinkAction.setText("Unlink"); + unlinkAction.setToolTipText("Unlink"); + unlinkAction.setImageDescriptor(Activator.imageDescriptorFromPlugin( + Activator.PLUGIN_ID, "icons/unlink.png")); + + actions.add(unionAction); + actions.add(intersectionAction); + actions.add(differenceAction); + actions.add(splitAction); + actions.add(linkAction); + actions.add(unlinkAction); + } + + boolean contains(ArrayList parentShape2sIds, Resource id) { + for (int i = 0; i < parentShape2sIds.size(); i++) { + if (parentShape2sIds.get(i).equals(id)) + return true; + + } + return false; + } + + boolean contains(Collection parentShape2sIds, Resource id) { + for (IEntity e : parentShape2sIds) { + if (e.getResource().equals(id)) + return true; + + } + return false; + } + + private boolean createBooleanOp(BooleanOperation op, G3DNode parent, + CSGShape shape1, List list) { + + resetShape(op.toShape()); //FIXME : stubcast + // new boolean operation is added to the first shape's parent + // the parent is the model + + Point3d refPos = G3DTools.getPoint(shape1.getLocalPosition()); + G3DTools.setTuple3(op.getLocalPosition(), refPos); + refPos.negate(); + G3DTools.addTuple3(shape1.getLocalPosition(), refPos); + op.removeRelatedStatements(ShapeEditorResources.csgResource.HasMainShape); + op.addStatement(ShapeEditorResources.csgResource.HasMainShape, shape1); + + if (!replaceShape(parent, shape1.toShape(), op.toShape())) { //FIXME : stubcast + return false; + } + //model.getConsistOfSet().remove(shape1); + for (int i = 1; i < list.size(); i++) { + CSGShape shape2 = new CSGShape(op.getGraph(),list.get(i).getResource()); + G3DTools.addTuple3(shape2.getLocalPosition(), refPos); + G3DNode shape2parent = shape2.getParent(); + if (shape2parent != null) { + // we'll must link before removing or shape will be deleted + //op.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape,shape2); + //if (!replaceShape(shape2parent, shape2, null)) { + // op.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape, shape2); + // // shape couldn't be removed so we'll remove the link + //} + + if (replaceShape(shape2parent, shape2.toShape(), null)) { //FIXME : stubcast + op.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape,shape2); + } + } + } + // Commit is not needed because this is final call in all transactions + //graph.commitChanges(ShapeEditorView.this); + return true; + } + + /** + * Replaces or removes parent from shape + * @param parent parent containing shape + * @param removed the shape + * @param added the replacing shape or null + * @return true if replacing or removing was successful + * @throws TransactionException + */ + private boolean replaceShape(G3DNode parent, Shape removed, Shape added) { + assert (parent != null); + assert (removed != null); + + + //CSGModel m = CSGModelFactory.create(parent.getGraph(),model); + if (parent.getResource().equals(this.parent.getModelResource())) { + // parent is model (rootnode). + // shape is connected to it with "Has Child" relation + parent.removeStatement(ShapeEditorResources.g3dResource.HasChild, removed); + if (added != null) { + parent.addStatement(ShapeEditorResources.g3dResource.HasChild, added); + } + } else { + // the first shape's parent is boolean operation + // so we must know if its connected as a primary shape or as a secondary shape + if (!parent.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) { + ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!",null); + return false; + } + BooleanOperation parentOp = new BooleanOperation(parent); + // listing all secondary shapes in the parent boolean operation + Collection parentShape2s = parentOp.getSecondaryShape(); + ArrayList parentShape2sIds = new ArrayList(); + for (CSGShape shape2 : parentShape2s) + parentShape2sIds.add(shape2.getResource()); + if (parentOp.getMainShape().getResource().equals(removed.getResource())) { + if (added == null) { + return false; + } + parent.removeStatement(ShapeEditorResources.csgResource.HasMainShape, removed); + parent.addStatement(ShapeEditorResources.csgResource.HasMainShape, added); + + } else if (contains(parentShape2sIds, removed.getResource())) { + + parent.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape, removed); + parent.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape, added); + + } else { + ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!",null); + //coreTC.cancelTransaction(); + return false; + } + } + return true; + } + + /** + * Resets shape to identity rotation and zero translation + * + * @param shape + */ + private void resetShape(Shape shape) { + G3DTools.resetTransformation(shape); + Graph graph = shape.getGraph(); + if (shape.isInstanceOf(ShapeEditorResources.csgResource.Primitive)) { + Primitive prim = new Primitive(shape); + Collection c = prim.getSizingProperty(); + if (c.size() == 0) + ErrorLogger.getDefault().logWarning("Shape does not contain sizing properties.", null); + + for (Property p : c) { + if (p.isInstanceOf(graph.getBuiltins().Double)) { + graph.setScalarDouble(p.getResource(), 1.0); + } else if (p.isInstanceOf(graph.getBuiltins().Integer)) { + graph.setScalarInteger(p.getResource(), 1); + } else { + ErrorLogger.getDefault().logWarning("Cannot handle sizing property " + p.getName() , null); + } + } + } + + } + + protected void showMessage(String s) { + parent.showMessage(s); + } + + @Override + public Collection getActions() { + return actions; + } + + + @Override + public void fillLocalToolBar(IToolBarManager manager) { + + } + + @Override + public void fillLocalPullDown(IMenuManager manager) { + + } + + @Override + public void dispose() { + + } + + @Override + public void run() { + + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/ParameterizationContribution.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/ParameterizationContribution.java new file mode 100644 index 00000000..3f1fefad --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/tools/ParameterizationContribution.java @@ -0,0 +1,680 @@ +package org.simantics.proconf.g3d.shapeeditor.tools; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Sash; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.forms.IFormColors; +import org.eclipse.ui.forms.events.ExpansionAdapter; +import org.eclipse.ui.forms.events.ExpansionEvent; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.Resource; +import org.simantics.equation.stubs.SecondOrderScalarPolynomial; +import org.simantics.g2d.stubs.anim.Animation; +import org.simantics.g2d.stubs.anim.Interpolator; +import org.simantics.layer0.utils.EntityFactory; +import org.simantics.layer0.utils.IEntity; +import org.simantics.layer0.utils.ResourceDebugUtils; +import org.simantics.proconf.browsing.GraphExplorer; +import org.simantics.proconf.browsing.GraphExplorerInputFactory; +import org.simantics.proconf.browsing.views.PropertyTable; +import org.simantics.proconf.g3d.actions.ContextAction; +import org.simantics.proconf.g3d.base.EditorContribution; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.common.StructuredResourceSelection; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; +import org.simantics.proconf.g3d.shapeeditor.common.ViewpointGenerator; +import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase; +import org.simantics.proconf.g3d.stubs.G3DModel; +import org.simantics.proconf.g3d.tools.OESelectionListener; +import org.simantics.proconf.g3d.tools.PropertyTree; +import org.simantics.utils.ui.jface.BaseSelectionProvider; + + +public class ParameterizationContribution implements EditorContribution { + + private ShapeEditorBase parent; + private List actions = new ArrayList(); + private Composite sideComposite; + private Sash sash; + + + public ParameterizationContribution(ThreeDimensionalEditorBase parent) { + this.parent = (ShapeEditorBase) parent; + } + + @Override + public void createControl(final Composite parentComposite) { + FormLayout flayout = new FormLayout(); + parentComposite.setLayout(flayout); + sash = new Sash(parentComposite,SWT.VERTICAL); + + sideComposite = new Composite(parentComposite,SWT.BORDER); + FormData data = new FormData(); + data.top = new FormAttachment(0, 0); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(sash, 0, SWT.LEFT); + data.bottom = new FormAttachment(100,0); + this.parent.getRenderingComposite().setLayoutData(data); + sideComposite.setLayout(new FillLayout(SWT.VERTICAL)); + data = new FormData(); + data.top = new FormAttachment(0, 0); + data.bottom = new FormAttachment(100,0); + data.right = new FormAttachment(100,0); + data.left = new FormAttachment(sash,0,SWT.RIGHT); + sideComposite.setLayoutData(data); + + final int limit = 20, percent = 50; + final FormData sashData = new FormData(); + sashData.left = new FormAttachment (percent, 0); + sashData.top = new FormAttachment(0, 0); + sashData.bottom = new FormAttachment(100,0); + + sash.setLayoutData (sashData); + sash.addListener (SWT.Selection, new Listener () { + public void handleEvent (Event e) { + Rectangle sashRect = sash.getBounds (); + Rectangle shellRect = parentComposite.getClientArea (); + int right = shellRect.width - sashRect.width - limit; + e.x = Math.max (Math.min (e.x, right), limit); + if (e.x != sashRect.x) { + sashData.left = new FormAttachment (0, e.x); + parentComposite.layout (); + } + } + }); + createForm(sideComposite); + + hierarchyExplorer.setInput(parent.getSessionContext(),GraphExplorerInputFactory.clone(hierarchyExplorer.getInput()) + .input(parent.getModelResource()) + .viewpoint(ViewpointGenerator.createObjectStructureViewpoint()) + .toInput()); + +// parameterExplorer.setInput(parent.getSessionContext(),GraphExplorerInputFactory.clone(parameterExplorer.getInput()) +// .input(parent.getModelResource()) +// .viewpoint(ViewpointGenerator.createObjectSizingParameterViewpoint(ShapeEditorResources.g3dResource.HasSizingParameter)) +// .toInput()); + parameterTable.setSession(parent.getSession()); + parameterTable.setInput(new StructuredResourceSelection(parent.getModelResource())); + + } + + @Override + public void disposeControl() { + sideComposite.dispose(); + sash.dispose(); + + } + + @Override + public void dispose() { + + } + + @Override + public void fillContextMenu(Graph graph, IMenuManager manager, + StructuredResourceSelection selection) { + + } + + @Override + public void fillLocalPullDown(IMenuManager manager) { + + } + + @Override + public void fillLocalToolBar(IToolBarManager manager) { + + } + + @Override + public Collection getActions() { + return actions; + } + + @Override + public String getName() { + return "Parameterization"; + } + + @Override + public void initialize(Graph graph) { + + } + + @Override + public void run() { + + } + + private ScrolledForm form; + private BaseSelectionProvider defaultInputSelectionProvider = new BaseSelectionProvider(); + protected FormToolkit toolkit; + + + + private void createForm(Composite parent) { + toolkit = new FormToolkit(parent.getDisplay()); + form = getToolkit().createScrolledForm(parent); + + GridLayout layout = new GridLayout(2, false); + form.getBody().setLayout(layout); + form.getBody().setLayoutData( + new GridData(GridData.FILL, GridData.FILL, true, true)); + + // By default make this ViewPart use a default ISelectionProvider + // that will offer the viewparts input resource as its selection. + // The Resource is wrapped into a ResourceSelection object. + // Any widgets created in createWidgets may override the default + // selection provider. + //getEditorSite().setSelectionProvider(defaultInputSelectionProvider); + + beforeCreateWidgets(); + createWidgets(); + + //reload(); + + form.setText(getFormText()); + + // Finally Set the default selection which will have an effect only + // if nothing in createWidgets has overridden the default selection + // provider. +// ISelection s = ISelectionUtils +// .createSelection(new StructuredResourceSelection( +// getInputResource())); +// defaultInputSelectionProvider.setSelection(s); + } + + + public ScrolledForm getActiveForm() { + return form; + } + + protected Composite getBody() { + return form.getBody(); + } + + public Composite newGridSection(int formColumns, int childColumns, + boolean equalWidth, boolean grabVertical, String text, + String description) { + return newGridSection(getBody(), formColumns, childColumns, equalWidth, + grabVertical, text, description); + } + + public Composite newGridSection(Composite parent, int formColumns, + int childColumns, boolean equalWidth, boolean grabVertical, + String text, String description) { + FormToolkit toolkit = getToolkit(); + + Section section = toolkit.createSection(parent, Section.DESCRIPTION + | Section.TWISTIE | Section.TITLE_BAR | Section.EXPANDED); + section.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, + grabVertical, formColumns, 1)); + section.addExpansionListener(new ExpansionAdapter() { + public void expansionStateChanged(ExpansionEvent e) { + //System.out.println("SinglePageTypeEditor: expansionStateChanged " + e); + //reflow(true); + } + }); + section.setText(text); + section.setDescription(description); + Composite sectionClient = toolkit.createComposite(section); + sectionClient.setLayout(new GridLayout(childColumns, equalWidth)); + sectionClient.setLayoutData(new GridData()); + section.setClient(sectionClient); + return sectionClient; + } + + public FormToolkit getToolkit() { + return toolkit; + } + + public void reflow(boolean flushCache) { + //System.out.println("FormTypeEditorBase.reflow(" + flushCache + ")"); + getActiveForm().reflow(flushCache); + } + + protected void beforeCreateWidgets() { + } + +// private TrackedText modelName = null; + StructuredResourceSelection hierarchySelection = new StructuredResourceSelection(); + StructuredResourceSelection parameterSelection = new StructuredResourceSelection(); + //GraphExplorer parameterExplorer; + PropertyTable parameterTable; + GraphExplorer hierarchyExplorer; + Button deleteParameterButton; + Button clearButton; + PropertyTree propertiesTree; + Button generateButton; + Button askButton; + Button overrideButton; + + protected String getFormText() { + return "Parameterization Editor"; + } + + protected void createWidgets() { + createModelPropertiesGroup(newGridSection(2, 1, false, false, "Model Properties", + "Basic properties for this viewpoint")); + createParametrizationGroup(newGridSection(2, 1, false, false, "Parameterization", + "Create parameterization for selected shapes")); + //getSite().setSelectionProvider(this); + } + + private void createParametrizationGroup(Composite parent) { + toolkit.paintBordersFor(parent); + toolkit.setBorderStyle(SWT.BORDER); + + overrideButton = toolkit.createButton(parent, "Overwrite previous parameterizations", SWT.CHECK); + overrideButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + askButton.setEnabled(overrideButton.getSelection()); + + } + }); + + + askButton = toolkit.createButton(parent, "Ask before overwriting", SWT.CHECK); + askButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + + + } + }); + askButton.setEnabled(false); + + generateButton = toolkit.createButton(parent, "Generate linear parameterization", SWT.PUSH); + generateButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + generateMappings(); + + } + }); + generateButton.setEnabled(false); + + + } + + private void createModelPropertiesGroup(final Composite parent) { + + toolkit.paintBordersFor(parent); + toolkit.setBorderStyle(SWT.BORDER); + + GridData gridData1 = new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1); + + + // Parameters + Label parameterLabel = toolkit.createLabel(parent, "Parameters:"); + parameterLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + parameterLabel.setLayoutData(gridData1); + +// parameterExplorer = new GraphExplorer(parent, SWT.SINGLE); //new OntologyExplorer("ParameterExplorer", this, getInput("ParameterExplorer", model.getId())); +// parameterExplorer.getViewer().addPostSelectionChangedListener(new OESelectionListener() { +// +// protected void resourceSelectionUpdated(StructuredResourceSelection sel) { +// parameterSelection = sel; +// if (parameterSelection.size() == 0) { +// deleteParameterButton.setEnabled(false); +// clearButton.setEnabled(false); +// } else { +// deleteParameterButton.setEnabled(true); +// clearButton.setEnabled(true); +// } +// updateGenerateButtonStatus(); +// } +// +// }); +// Tree oe = parameterExplorer.getTree(); +// toolkit.adapt(oe, true, true); + + parameterTable = new PropertyTable(parent,SWT.NONE); + parameterTable.getViewer().addPostSelectionChangedListener(new OESelectionListener() { + + protected void resourceSelectionUpdated(StructuredResourceSelection sel) { + parameterSelection = sel; + if (parameterSelection.size() == 0) { + deleteParameterButton.setEnabled(false); + clearButton.setEnabled(false); + } else { + deleteParameterButton.setEnabled(true); + clearButton.setEnabled(true); + } + updateGenerateButtonStatus(); + } + + }); + + GridData gd3 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); + gd3.heightHint = 50; + //oe.setLayoutData(gd3); + + parameterTable.setLayoutData(gd3); + + // Buttons to add and remove parameters + toolkit.createLabel(parent, ""); + Composite buttons = toolkit.createComposite(parent); + + buttons.setLayout(new FillLayout(SWT.HORIZONTAL)); + Button newParameterButton = toolkit.createButton(buttons, "New Parameter", SWT.PUSH); + newParameterButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + InputDialog dialog = new InputDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(),"New Parameter","Enter parameter's name","new parameter",null); + if (dialog.open() == InputDialog.CANCEL) + return; + final String name = dialog.getValue(); + if (name.length() < 1) + return; // TODO : show error + + ParameterizationContribution.this.parent.getSession().asyncWrite(new GraphRequestAdapter() { + public GraphRequestStatus perform(Graph g) throws Exception { + //fi.vtt.simantics.layer0.stubs.Double parameter = DoubleFactory.createDefault(g); + //getModel(g).addStatement(ShapeEditorResources.g3dResource.HasSizingParameter, parameter); + //parameter.setValue(new double[]{1.0}); + //parameter.setName(name); + Resource parameter = ParameterizationContribution.this.parent.getModel(g).addRelatedScalarDouble(ShapeEditorResources.g3dResource.HasSizingParameter, 1.0).getResource(); + IEntity thing = EntityFactory.create(g,parameter); + thing.setName(name); + return GraphRequestStatus.transactionComplete(); + }; + }); + + + } + }); + deleteParameterButton = toolkit.createButton(buttons, "Delete Parameter", SWT.PUSH); + deleteParameterButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + //StructuredResourceSelection s = (StructuredResourceSelection)parameterScheme.getSelection(); + final StructuredResourceSelection s = parameterSelection; + if (s.size() != 1) + return; + // we'll have to start write transaction, since we may have to change the graph + ParameterizationContribution.this.parent.getSession().asyncWrite(new GraphRequestAdapter() { + boolean proceed; + IEntity selectedParameter; + public GraphRequestStatus perform(Graph g) throws Exception { + selectedParameter = EntityFactory.create(g,s.getSelectionList().get(0)); + + Collection parameters = selectedParameter.getRelatedObjects(ShapeEditorResources.g3dResource.HasSizingParameter); + if (parameters.size() > 0) { + final MessageDialog dialog = new MessageDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(),"Deleting a parameter",null,"Parameter is in use, doe you wan't to remove it?",MessageDialog.QUESTION,new String[]{"OK","Cancel"},1); + parent.getDisplay().syncExec(new Runnable() { + @Override + public void run() { + proceed = (dialog.open() != 1); + } + }); + if (proceed) { + ParameterizationContribution.this.parent.getModel(g).removeStatement(ShapeEditorResources.g3dResource.HasSizingParameter,selectedParameter); + } + } + + return GraphRequestStatus.transactionComplete(); + } + }); + } + }); + deleteParameterButton.setEnabled(false); + + clearButton = toolkit.createButton(buttons, "Clear Parameter", SWT.PUSH); + clearButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + final StructuredResourceSelection s = parameterSelection; + if (s.size() != 1) + return; + ParameterizationContribution.this.parent.getSession().asyncWrite(new GraphRequestAdapter() { + boolean proceed; + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + IEntity selectedParameter = EntityFactory.create(g,s.getSelectionList().get(0)); + Collection equations = selectedParameter.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget); + final String name = selectedParameter.getName(); + if (equations.size() > 0) { + final MessageDialog dialog = new MessageDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(),"Clearing a parameter",null,"Do you wan't to clear parameterization for "+ name + " ?\nIt has " + equations.size() + " mappings.",MessageDialog.QUESTION,new String[]{"OK","Cancel"},1); + parent.getDisplay().syncExec(new Runnable() { + public void run() { + proceed = (dialog.open() != 1); + }; + }); + if (proceed) { + for (IEntity eq : equations) { + eq.removeRelatedStatements(ShapeEditorResources.equationResource.HasSource); + eq.removeRelatedStatements(ShapeEditorResources.equationResource.HasTarget); + } + return GraphRequestStatus.transactionComplete(); + } + } + return GraphRequestStatus.transactionCancel(); + } + }); + + + } + }); + clearButton.setEnabled(false); + + Label hierarchyLabel = toolkit.createLabel(parent, "Model Hierarchy:"); + hierarchyLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + hierarchyLabel.setLayoutData(gridData1); + + hierarchyExplorer = new GraphExplorer(parent,SWT.MULTI); //new OntologyExplorer("HierarchyExplorer", this, getInput("HierarchyExplorer", model.getId())); + Tree oeh = hierarchyExplorer.getTree();//hierarchyExplorer.getControl(parent, 1, OntologyExplorer.OntologyTree, SWT.MULTI); + toolkit.adapt(oeh, true, true); + + GridData gd4 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); + gd4.heightHint = 200; + oeh.setLayoutData(gd4); + hierarchyExplorer.getViewer().addPostSelectionChangedListener(new OESelectionListener() { + + protected void resourceSelectionUpdated(StructuredResourceSelection sel) { + hierarchySelection = sel; + updatePropertiesTable(); + updateGenerateButtonStatus(); + } + + private void updatePropertiesTable() { + propertiesTree.setProperties(hierarchySelection); + + } + + }); + + Label propertiesLabel = toolkit.createLabel(parent, "Available properties:"); + propertiesLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + propertiesLabel.setLayoutData(gridData1); + + //propertiesTable = toolkit.createTable(parent, SWT.MULTI); + Tree tree = toolkit.createTree(parent, SWT.MULTI); + propertiesTree = new PropertyTree(tree,ParameterizationContribution.this.parent.getSession()); + // + GridData gd5 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); + gd5.heightHint = 200; + //propertiesTable.setLayoutData(gd5); + tree.setLayoutData(gd5); + tree.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + updateGenerateButtonStatus(); + } + + }); + + + } + + private void updateGenerateButtonStatus() { + if (parameterSelection.size() == 0) { + generateButton.setEnabled(false); + return; + } + if (hierarchySelection.size() == 0) { + generateButton.setEnabled(false); + return; + } + if (propertiesTree.getTree().getSelection().length == 0) { + generateButton.setEnabled(false); + return; + } + generateButton.setEnabled(true); + } + + List res; + + private void generateMappings() { + final StructuredResourceSelection selectedShapes = hierarchySelection; + final StructuredResourceSelection selectedParameter = parameterSelection; + + final boolean override = overrideButton.getSelection(); + final boolean ask = askButton.getSelection(); + //TreeItem[] selectedProperties = propertiesTree.getTree().getSelection(); + + assert (selectedParameter.size() == 1); + assert (selectedShapes.size() > 0); + //assert(selectedProperties.length > 0); + parent.getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + //fi.vtt.simantics.layer0.stubs.Double parameter = DoubleFactory.create(g,selectedParameter.getSelectionList().get(0)); + IEntity parameter = EntityFactory.create(g,selectedParameter.getSelectionList().get(0)); + Collection prop = parameter.getRelatedObjects(ShapeEditorResources.g3dResource.HasDefaultDoubleValue); + //fi.vtt.simantics.layer0.stubs.Double defaultValue; + double value = g.getScalarDouble(parameter.getResource()); + if (prop.size() == 0) { + //defaultValue = DoubleFactory.createDefault(g); + //parameter.addStatement(ShapeEditorResources.g3dResource.HasDefaultDoubleValue, defaultValue); + parameter.addRelatedScalarDouble(ShapeEditorResources.g3dResource.HasDefaultDoubleValue, value); + } else { + //defaultValue = DoubleFactory.create(prop.iterator().next()); + g.setScalarDouble(prop.iterator().next().getResource(),value); + } + //defaultValue.setValue(parameter.getValue()); + final Graph graph = g; + parent.getRenderingComposite().getDisplay().syncExec(new Runnable() { + public void run() { + res = propertiesTree.findLeafPropertyInstances(graph, selectedShapes.getSelectionList()); + }; + }); + + + double refValue = parameter.toProperty().getScalarDouble(); + ArrayList mappedProperties = new ArrayList(); + + for (Resource r : res) { + IEntity propertyThing = EntityFactory.create(g,r); + assert (propertyThing.isInstanceOf(g.getBuiltins().Double)); + final String name = ResourceDebugUtils.getReadableNameForEntity(propertyThing); + double rb = propertyThing.toProperty().getScalarDouble(); + System.out.println("Mapping to " + name + " " + rb); + Collection equations = propertyThing.getRelatedObjects(ShapeEditorResources.equationResource.HasSource); + if (equations.size() != 0) { + mappedProperties.add(propertyThing.getResource()); + if (override) { + System.out.println("Override"); + boolean over = true; + if (ask) { + IEntity t = propertyThing; + while (t.isInstanceOf(g.getBuiltins().Property)) { + Collection ts = t.getRelatedObjects(g.getBuiltins().PropertyOf); + // FIXME : traverse all possible routes + t = ts.iterator().next(); + } + //StructuredResourceSelection selection = new StructuredResourceSelection(t.getResource()); + // TODO : do the selection! + //hierarchyScheme.setSelection(selection); + //fireSelectionChanged(); + MessageDialog dialog = new MessageDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(), + "Override mapping", + null, + "Override mapping to property of highlighted shape?", + MessageDialog.QUESTION, new String[] { + "Yes","No", "Cancel" }, 0); + int i = dialog.open(); + if (i == 2) + return GraphRequestStatus.transactionCancel(); + over = (i == 0); + } + if (over) { + + } + } else { + if (equations.size() != 1) { + throw new RuntimeException("One property can have only one euquation as source function."); + } + IEntity equation = equations.iterator().next(); + if (!equation.isInstanceOf(ShapeEditorResources.equationResource.SecondOrderScalarPolynomial)) { + throw new RuntimeException("Only Second order scalar polynomials are supported"); + } + SecondOrderScalarPolynomial s = new SecondOrderScalarPolynomial(equation); + s.setA(new double[]{0.0}); + s.setB(new double[]{rb / refValue}); + s.setC(new double[]{0.0}); + + } + } else { //override + // create relation + SecondOrderScalarPolynomial s = SecondOrderScalarPolynomial.createDefault(g); + s.setA(new double[]{0.0}); + s.setB(new double[]{rb / refValue}); + s.setC(new double[]{0.0}); + + // these relations have been instantiated, but addStatements won't delete them so we have to delete them manually. + s.removeRelatedStatements(ShapeEditorResources.equationResource.HasTarget); + s.removeRelatedStatements(ShapeEditorResources.equationResource.HasSource); + + parameter.addStatement(ShapeEditorResources.equationResource.HasTarget, s); + + s.addStatement(ShapeEditorResources.equationResource.HasTarget, propertyThing); + mappedProperties.add(propertyThing.getResource()); + } + + } + G3DModel model = parent.getModel(g); + Collection animations = model.getAnimation(); + for (Animation animation : animations) { + Collection interpolators = animation.getInterpolator(); + for (Interpolator interpolator : interpolators) { + IEntity target = interpolator.getTarget(); + for (Resource property : mappedProperties) { + if (target.getResource().equals(property)) { + ShapeEditorResources.curveBuilder.createDefault(interpolator); + } + } + } + } + return GraphRequestStatus.transactionComplete(); + } + }); + + + + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/CSGModellingView.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/CSGModellingView.java new file mode 100644 index 00000000..f2b8c84b --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/CSGModellingView.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.views; + +import org.eclipse.swt.widgets.Composite; + +import org.simantics.db.management.ISessionContext; +import org.simantics.layer0.utils.viewpoints.ResourceViewpoint; +import org.simantics.proconf.browsing.GraphExplorer; +import org.simantics.proconf.browsing.views.GraphExplorerView; +import org.simantics.proconf.g3d.shapeeditor.common.ViewpointGenerator; + +public class CSGModellingView extends GraphExplorerView { + + @Override + protected GraphExplorer createExplorer(Composite parent) { + return super.createExplorer(parent); + } + + @Override + protected ResourceViewpoint getViewpoint(ISessionContext context) { + return ViewpointGenerator.createViewpoint(); + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ParameterizationEditor.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ParameterizationEditor.java new file mode 100644 index 00000000..07dc17cd --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ParameterizationEditor.java @@ -0,0 +1,587 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.views; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.forms.IFormColors; +import org.simantics.proconf.g3d.csg.stubs.CSGModel; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.Resource; +import org.simantics.equation.stubs.SecondOrderScalarPolynomial; +import org.simantics.g2d.stubs.anim.Animation; +import org.simantics.g2d.stubs.anim.Interpolator; +import org.simantics.layer0.utils.ResourceDebugUtils; +import org.simantics.layer0.utils.IEntity; +import org.simantics.layer0.utils.EntityFactory; +import org.simantics.proconf.browsing.GraphExplorer; +import org.simantics.proconf.browsing.GraphExplorerInputFactory; +import org.simantics.proconf.g3d.common.StructuredResourceSelection; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; +import org.simantics.proconf.g3d.shapeeditor.common.ViewpointGenerator; +import org.simantics.proconf.g3d.tools.OESelectionListener; +import org.simantics.proconf.g3d.tools.PropertyTree; +import org.simantics.proconf.g3d.views.SinglePageResourceEditor; +import org.simantics.utils.ui.widgets.TrackedModifyEvent; +import org.simantics.utils.ui.widgets.TrackedModifyListener; +import org.simantics.utils.ui.widgets.TrackedText; + + +public class ParameterizationEditor extends SinglePageResourceEditor { //implements ISelectionProvider{ + + //ParameterizedCSGModel model; + Resource modelResource; + private TrackedText modelName = null; + StructuredResourceSelection hierarchySelection = new StructuredResourceSelection(); + StructuredResourceSelection parameterSelection = new StructuredResourceSelection(); + GraphExplorer parameterExplorer; + GraphExplorer hierarchyExplorer; + Button deleteParameterButton; + Button clearButton; + PropertyTree propertiesTree; + Button generateButton; + Button askButton; + Button overrideButton; + Composite parent; + + + @Override + protected String getFormText() { + return "Parameterization Editor"; + } + +// @Override +// protected void beforeCreateWidgets() { +// if (!(getInputResource().isInstanceOf(GlobalIdMap.get(CSGModelingOntologyMapping.PARAMETERIZED_CSG_MODEL)))) +// throw new RuntimeException("Trying to open resource that is not paramaterized CSG model"); +// model = ParameterizedCSGModelFactory.create(getInputResource()); +// } + + + + @Override + protected void createWidgets() { + createModelPropertiesGroup(newGridSection(2, 2, false, false, "Model Properties", + "Basic properties for this viewpoint")); + createParametrizationGroup(newGridSection(2, 2, false, false, "Parameterization", + "Create parameterization for selected shapes")); + //getSite().setSelectionProvider(this); + } + + @Override + public void reload(Graph graph) { + modelResource = getInputResource(); + parent.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + reload(); + } + }); + + } + + public void reload() { + + hierarchyExplorer.setInput(getSessionContext(),GraphExplorerInputFactory.clone(hierarchyExplorer.getInput()) + .input(modelResource) + .viewpoint(ViewpointGenerator.createObjectStructureViewpoint()) + .toInput()); + + parameterExplorer.setInput(getSessionContext(),GraphExplorerInputFactory.clone(parameterExplorer.getInput()) + .input(modelResource) + .viewpoint(ViewpointGenerator.createObjectSizingParameterViewpoint(ShapeEditorResources.g3dResource.HasSizingParameter)) + .toInput()); + + } + + private void createParametrizationGroup(Composite parent) { + toolkit.paintBordersFor(parent); + toolkit.setBorderStyle(SWT.BORDER); + + overrideButton = toolkit.createButton(parent, "Overwrite previous parameterizations", SWT.CHECK); + overrideButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + askButton.setEnabled(overrideButton.getSelection()); + + } + }); + + + askButton = toolkit.createButton(parent, "Ask before overwriting", SWT.CHECK); + askButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + + + } + }); + askButton.setEnabled(false); + + generateButton = toolkit.createButton(parent, "Generate linear parameterization", SWT.PUSH); + generateButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + generateMappings(); + + } + }); + generateButton.setEnabled(false); + + + } + + private CSGModel getModel(Graph graph) { + return new CSGModel(graph, modelResource); + } + + private void createModelPropertiesGroup(Composite p) { + parent = p; + toolkit.paintBordersFor(parent); + toolkit.setBorderStyle(SWT.BORDER); + + GridData gridData1 = new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1); + GridData gridData2 = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); + + // Name + Label l1 = toolkit.createLabel(parent, "Name:"); + l1.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + Text text = toolkit.createText(parent, "TODO: Insert model's name here", SWT.SINGLE); + GridData textLayout = new GridData(GridData.FILL, GridData.FILL, true, true); + text.setLayoutData(textLayout); + modelName = new TrackedText(text); + modelName.addModifyListener(new TrackedModifyListener(){ + @Override + public void modifyText(TrackedModifyEvent e) { + final String name = e.getText(); + getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + getModel(g).setName(name); + return GraphRequestStatus.transactionComplete(); + } + }); + } + }); + + l1.setLayoutData(gridData1); + text.setLayoutData(gridData2); + + + // Parameters + Label parameterLabel = toolkit.createLabel(parent, "Parameters:"); + parameterLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + parameterLabel.setLayoutData(gridData1); + + parameterExplorer = new GraphExplorer(parent, SWT.SINGLE); //new OntologyExplorer("ParameterExplorer", this, getInput("ParameterExplorer", model.getId())); + parameterExplorer.getViewer().addPostSelectionChangedListener(new OESelectionListener() { + + protected void resourceSelectionUpdated(StructuredResourceSelection sel) { + parameterSelection = sel; + if (parameterSelection.size() == 0) { + deleteParameterButton.setEnabled(false); + clearButton.setEnabled(false); + } else { + deleteParameterButton.setEnabled(true); + clearButton.setEnabled(true); + } + updateGenerateButtonStatus(); + } + + }); + Tree oe = parameterExplorer.getTree(); + toolkit.adapt(oe, true, true); + GridData gd3 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); + gd3.heightHint = 50; + oe.setLayoutData(gd3); +// parameterExplorer.init(getLastMemento(), ViewpointUtils.getModelledHandler(parameterExplorer.getGraph(), Builtins.DefaultViewpointId), null, ViewLabelProviderDecorationSettings.DEFAULT, new MenuAboutToShowAction(), new NullAdditionAction(), false); +// parameterScheme = new ParameterSelectionScheme(parameterExplorer); +// parameterExplorer.setSelectionScheme(parameterScheme); + + // Buttons to add and remove parameters + toolkit.createLabel(parent, ""); + Composite buttons = toolkit.createComposite(parent); + + buttons.setLayout(new FillLayout(SWT.HORIZONTAL)); + Button newParameterButton = toolkit.createButton(buttons, "New Parameter", SWT.PUSH); + newParameterButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + InputDialog dialog = new InputDialog(ParameterizationEditor.this.getSite().getShell(),"New Parameter","Enter parameter's name","new parameter",null); + if (dialog.open() == InputDialog.CANCEL) + return; + final String name = dialog.getValue(); + if (name.length() < 1) + return; // TODO : show error + + getSession().asyncWrite(new GraphRequestAdapter() { + public GraphRequestStatus perform(Graph g) throws Exception { + //fi.vtt.simantics.layer0.stubs.Double parameter = DoubleFactory.createDefault(g); + //getModel(g).addStatement(ShapeEditorResources.g3dResource.HasSizingParameter, parameter); + //parameter.setValue(new double[]{1.0}); + //parameter.setName(name); + Resource parameter = getModel(g).addRelatedScalarDouble(ShapeEditorResources.g3dResource.HasSizingParameter, 1.0).getResource(); + IEntity thing = EntityFactory.create(g,parameter); + thing.setName(name); + return GraphRequestStatus.transactionComplete(); + }; + }); + + + } + }); + deleteParameterButton = toolkit.createButton(buttons, "Delete Parameter", SWT.PUSH); + deleteParameterButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + //StructuredResourceSelection s = (StructuredResourceSelection)parameterScheme.getSelection(); + final StructuredResourceSelection s = parameterSelection; + if (s.size() != 1) + return; + // we'll have to start write transaction, since we may have to change the graph + getSession().asyncWrite(new GraphRequestAdapter() { + boolean proceed; + IEntity selectedParameter; + public GraphRequestStatus perform(Graph g) throws Exception { + selectedParameter = EntityFactory.create(g,s.getSelectionList().get(0)); + + Collection parameters = selectedParameter.getRelatedObjects(ShapeEditorResources.g3dResource.HasSizingParameter); + if (parameters.size() > 0) { + final MessageDialog dialog = new MessageDialog(ParameterizationEditor.this.getSite().getShell(),"Deleting a parameter",null,"Parameter is in use, doe you wan't to remove it?",MessageDialog.QUESTION,new String[]{"OK","Cancel"},1); + parent.getDisplay().syncExec(new Runnable() { + @Override + public void run() { + proceed = (dialog.open() != 1); + } + }); + if (proceed) { + getModel(g).removeStatement(ShapeEditorResources.g3dResource.HasSizingParameter,selectedParameter); + } + } + + return GraphRequestStatus.transactionComplete(); + } + }); + } + }); + deleteParameterButton.setEnabled(false); + + clearButton = toolkit.createButton(buttons, "Clear Parameter", SWT.PUSH); + clearButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + final StructuredResourceSelection s = parameterSelection; + if (s.size() != 1) + return; + getSession().asyncWrite(new GraphRequestAdapter() { + boolean proceed; + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + IEntity selectedParameter = EntityFactory.create(g,s.getSelectionList().get(0)); + Collection equations = selectedParameter.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget); + final String name = selectedParameter.getName(); + if (equations.size() > 0) { + final MessageDialog dialog = new MessageDialog(ParameterizationEditor.this.getSite().getShell(),"Clearing a parameter",null,"Do you wan't to clear parameterization for "+ name + " ?\nIt has " + equations.size() + " mappings.",MessageDialog.QUESTION,new String[]{"OK","Cancel"},1); + parent.getDisplay().syncExec(new Runnable() { + public void run() { + proceed = (dialog.open() != 1); + }; + }); + if (proceed) { + for (IEntity eq : equations) { + eq.removeRelatedStatements(ShapeEditorResources.equationResource.HasSource); + eq.removeRelatedStatements(ShapeEditorResources.equationResource.HasTarget); + } + return GraphRequestStatus.transactionComplete(); + } + } + return GraphRequestStatus.transactionCancel(); + } + }); + + + } + }); + clearButton.setEnabled(false); + + Label hierarchyLabel = toolkit.createLabel(parent, "Model Hierarchy:"); + hierarchyLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + hierarchyLabel.setLayoutData(gridData1); + + hierarchyExplorer = new GraphExplorer(parent,SWT.MULTI); //new OntologyExplorer("HierarchyExplorer", this, getInput("HierarchyExplorer", model.getId())); + Tree oeh = hierarchyExplorer.getTree();//hierarchyExplorer.getControl(parent, 1, OntologyExplorer.OntologyTree, SWT.MULTI); + toolkit.adapt(oeh, true, true); + + GridData gd4 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); + gd4.heightHint = 200; + oeh.setLayoutData(gd4); + hierarchyExplorer.getViewer().addPostSelectionChangedListener(new OESelectionListener() { + + protected void resourceSelectionUpdated(StructuredResourceSelection sel) { + hierarchySelection = sel; + updatePropertiesTable(); + updateGenerateButtonStatus(); + } + + private void updatePropertiesTable() { + propertiesTree.setProperties(hierarchySelection); + + } + + }); + //hierarchyExplorer.init(getLastMemento(), ViewpointUtils.getModelledHandler(hierarchyExplorer.getGraph(), CSGModelingOntologyMapping.CSG_MODEL_HIERARCHY_VIEWPOINT), null, ViewLabelProviderDecorationSettings.DEFAULT, new MenuAboutToShowAction(), new NullAdditionAction(), false); +// hierarchyScheme = new HierarchySelectionScheme(hierarchyExplorer); +// hierarchyExplorer.setSelectionScheme(hierarchyScheme); +// hierarchyExplorer.hookPageSelection(this); + Label propertiesLabel = toolkit.createLabel(parent, "Available properties:"); + propertiesLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + propertiesLabel.setLayoutData(gridData1); + + //propertiesTable = toolkit.createTable(parent, SWT.MULTI); + Tree tree = toolkit.createTree(parent, SWT.MULTI); + propertiesTree = new PropertyTree(tree,getSession()); + // + GridData gd5 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); + gd5.heightHint = 200; + //propertiesTable.setLayoutData(gd5); + tree.setLayoutData(gd5); + tree.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + updateGenerateButtonStatus(); + } + + }); + + + } + +// private class ParameterSelectionScheme extends AbstractSelectionScheme { +// +// public ParameterSelectionScheme(OntologyExplorer explorer) { +// super(explorer); +// } +// +// @Override +// protected Resource getResourceForSelection(TreeNode selected) { +// Resource resource = explorer.getCoreResource(selected); +// System.out.println("Parameter Tree Selection : " + resource.getId()); +// return resource; +// } +// +// @Override +// protected void resourceSelectionUpdated() { +// if (selection.size() == 0) { +// deleteParameterButton.setEnabled(false); +// clearButton.setEnabled(false); +// } else { +// deleteParameterButton.setEnabled(true); +// clearButton.setEnabled(true); +// } +// updateGenerateButtonStatus(); +// } +// } +// +// private class HierarchySelectionScheme extends AbstractSelectionScheme { +// +// public HierarchySelectionScheme(OntologyExplorer explorer) { +// super(explorer); +// } +// +// @Override +// protected Resource getResourceForSelection(TreeNode selected) { +// Resource resource = explorer.getCoreResource(selected); +// System.out.println("Hierarchy Tree Selection : " + resource.getId()); +// return resource; +// } +// +// @Override +// protected void resourceSelectionUpdated() { +// updatePropertiesTable(); +// updateGenerateButtonStatus(); +// } +// +// private void updatePropertiesTable() { +// propertiesTree.setProperties(selection); +// +// } +// +// } + +// private boolean contains(Resource list[], Resource value) { +// for (int i = 0; i < list.length; i++) { +// if (list[i].equals(value)) +// return true; +// } +// return false; +// } + + private void updateGenerateButtonStatus() { + if (parameterSelection.size() == 0) { + generateButton.setEnabled(false); + return; + } + if (hierarchySelection.size() == 0) { + generateButton.setEnabled(false); + return; + } + if (propertiesTree.getTree().getSelection().length == 0) { + generateButton.setEnabled(false); + return; + } + generateButton.setEnabled(true); + } + + List res; + + private void generateMappings() { + final StructuredResourceSelection selectedShapes = hierarchySelection; + final StructuredResourceSelection selectedParameter = parameterSelection; + + final boolean override = overrideButton.getSelection(); + final boolean ask = askButton.getSelection(); + //TreeItem[] selectedProperties = propertiesTree.getTree().getSelection(); + + assert (selectedParameter.size() == 1); + assert (selectedShapes.size() > 0); + //assert(selectedProperties.length > 0); + getSession().asyncWrite(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + //fi.vtt.simantics.layer0.stubs.Double parameter = DoubleFactory.create(g,selectedParameter.getSelectionList().get(0)); + IEntity parameter = EntityFactory.create(g,selectedParameter.getSelectionList().get(0)); + Collection prop = parameter.getRelatedObjects(ShapeEditorResources.g3dResource.HasDefaultDoubleValue); + //fi.vtt.simantics.layer0.stubs.Double defaultValue; + double value = g.getScalarDouble(parameter.getResource()); + if (prop.size() == 0) { + //defaultValue = DoubleFactory.createDefault(g); + //parameter.addStatement(ShapeEditorResources.g3dResource.HasDefaultDoubleValue, defaultValue); + parameter.addRelatedScalarDouble(ShapeEditorResources.g3dResource.HasDefaultDoubleValue, value); + } else { + //defaultValue = DoubleFactory.create(prop.iterator().next()); + g.setScalarDouble(prop.iterator().next().getResource(),value); + } + //defaultValue.setValue(parameter.getValue()); + final Graph graph = g; + parent.getDisplay().syncExec(new Runnable() { + public void run() { + res = propertiesTree.findLeafPropertyInstances(graph, selectedShapes.getSelectionList()); + }; + }); + + + double refValue = parameter.toProperty().getScalarDouble(); + ArrayList mappedProperties = new ArrayList(); + + for (Resource r : res) { + IEntity propertyThing = EntityFactory.create(g,r); + assert (propertyThing.isInstanceOf(g.getBuiltins().Double)); + final String name = ResourceDebugUtils.getReadableNameForEntity(propertyThing); + double rb = propertyThing.toProperty().getScalarDouble(); + System.out.println("Mapping to " + name + " " + rb); + Collection equations = propertyThing.getRelatedObjects(ShapeEditorResources.equationResource.HasSource); + if (equations.size() != 0) { + mappedProperties.add(propertyThing.getResource()); + if (override) { + System.out.println("Override"); + boolean over = true; + if (ask) { + IEntity t = propertyThing; + while (t.isInstanceOf(g.getBuiltins().Property)) { + Collection ts = t.getRelatedObjects(g.getBuiltins().PropertyOf); + // FIXME : traverse all possible routes + t = ts.iterator().next(); + } + //StructuredResourceSelection selection = new StructuredResourceSelection(t.getResource()); + // TODO : do the selection! + //hierarchyScheme.setSelection(selection); + //fireSelectionChanged(); + MessageDialog dialog = new MessageDialog(ParameterizationEditor.this.getSite().getShell(), + "Override mapping", + null, + "Override mapping to property of highlighted shape?", + MessageDialog.QUESTION, new String[] { + "Yes","No", "Cancel" }, 0); + int i = dialog.open(); + if (i == 2) + return GraphRequestStatus.transactionCancel(); + over = (i == 0); + } + if (over) { + + } + } else { + if (equations.size() != 1) { + throw new RuntimeException("One property can have only one euquation as source function."); + } + IEntity equation = equations.iterator().next(); + if (!equation.isInstanceOf(ShapeEditorResources.equationResource.SecondOrderScalarPolynomial)) { + throw new RuntimeException("Only Second order scalar polynomials are supported"); + } + SecondOrderScalarPolynomial s = new SecondOrderScalarPolynomial(equation); + s.setA(new double[]{0.0}); + s.setB(new double[]{rb / refValue}); + s.setC(new double[]{0.0}); + + } + } else { //override + // create relation + SecondOrderScalarPolynomial s = SecondOrderScalarPolynomial.createDefault(g); + s.setA(new double[]{0.0}); + s.setB(new double[]{rb / refValue}); + s.setC(new double[]{0.0}); + + // FIXME : these relations have been instantiated, but addStatements won't delete them so we have to delete them manually. + s.removeRelatedStatements(ShapeEditorResources.equationResource.HasTarget); + s.removeRelatedStatements(ShapeEditorResources.equationResource.HasSource); + + parameter.addStatement(ShapeEditorResources.equationResource.HasTarget, s); + + s.addStatement(ShapeEditorResources.equationResource.HasTarget, propertyThing); + mappedProperties.add(propertyThing.getResource()); + } + + } + CSGModel model = getModel(g); + Collection animations = model.getAnimation(); + for (Animation animation : animations) { + Collection interpolators = animation.getInterpolator(); + for (Interpolator interpolator : interpolators) { + IEntity target = interpolator.getTarget(); + for (Resource property : mappedProperties) { + if (target.getResource().equals(property)) { + ShapeEditorResources.curveBuilder.createDefault(interpolator); + } + } + } + } + return GraphRequestStatus.transactionComplete(); + } + }); + + + + } + +} + diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorBase.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorBase.java new file mode 100644 index 00000000..9c1490d7 --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorBase.java @@ -0,0 +1,628 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.views; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.simantics.db.ContextGraph; +import org.simantics.db.Graph; +import org.simantics.db.GraphRequestAdapter; +import org.simantics.db.GraphRequestStatus; +import org.simantics.db.GraphRequestWithResult; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.management.ISessionContext; +import org.simantics.equation.solver.Solver; +import org.simantics.layer0.stubs.Property; +import org.simantics.layer0.utils.EntityFactory; +import org.simantics.layer0.utils.IEntity; +import org.simantics.proconf.g3d.actions.InteractiveAction; +import org.simantics.proconf.g3d.actions.TranslateAction; +import org.simantics.proconf.g3d.base.G3DTools; +import org.simantics.proconf.g3d.base.JmeRenderingComponent; +import org.simantics.proconf.g3d.base.ScenegraphAdapter; +import org.simantics.proconf.g3d.base.ScenegraphAdapterImpl; +import org.simantics.proconf.g3d.base.SelectionAdapter; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorProvider; +import org.simantics.proconf.g3d.common.StructuredResourceSelection; +import org.simantics.proconf.g3d.csg.stubs.CSGModel; +import org.simantics.proconf.g3d.csg.stubs.Primitive; +import org.simantics.proconf.g3d.dnd.DropListener; +import org.simantics.proconf.g3d.scenegraph.AbstractGraphicsNode; +import org.simantics.proconf.g3d.scenegraph.IGeometryNode; +import org.simantics.proconf.g3d.scenegraph.IGraphicsNode; +import org.simantics.proconf.g3d.scenegraph.ISelectableNode; +import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; +import org.simantics.proconf.g3d.shapeeditor.actions.ExportAction; +import org.simantics.proconf.g3d.shapeeditor.actions.ImportAction; +import org.simantics.proconf.g3d.shapeeditor.scenegraph.CSGShapeNode; +import org.simantics.proconf.g3d.shapeeditor.tools.AnimationContribution; +import org.simantics.proconf.g3d.shapeeditor.tools.CSGModellingContribution; +import org.simantics.proconf.g3d.shapeeditor.tools.ParameterizationContribution; +import org.simantics.proconf.g3d.shapes.GridShape; +import org.simantics.proconf.g3d.stubs.G3DModel; +import org.simantics.proconf.g3d.stubs.G3DNode; +import org.simantics.proconf.g3d.stubs.Shape; +import org.simantics.utils.ErrorLogger; +import org.simantics.utils.ui.jface.MenuTools; + +public class ShapeEditorBase extends ThreeDimensionalEditorBase { + + // currently each 3D-model has a root object which is ShapeGroup + protected Resource model = null; + + protected boolean isParameterized; + + private Action exportAction; + private Action importAction; + + public ShapeEditorBase(ISessionContext session) { + super(session); + addEditorContribution(new CSGModellingContribution(this)); + addEditorContribution(new AnimationContribution(this)); + addEditorContribution(new ParameterizationContribution(this)); + } + + public ShapeEditorBase(ISessionContext session, JmeRenderingComponent component) { + super(session,component); + addEditorContribution(new CSGModellingContribution(this)); + addEditorContribution(new AnimationContribution(this)); + addEditorContribution(new ParameterizationContribution(this)); + } + + @Override + protected ScenegraphAdapter createScenegraphAdapter() { + return new ShapeEditorAdapter(session, getRenderingComponent()); + } + + @Override + public void createControl(Graph graph,Composite parent) { + super.createControl(graph,parent); + getRenderingComponent().getNoCastRoot().attachChild(GridShape.getShape(getRenderingComponent().getDisplaySystem().getRenderer(), 10, 1.f)); + } + +// private void loadGroup(Graph graph) { +// assert (model != null); +// adapter.addOutbound(EntityFactory.create(graph,model)); +// //assert (abstractGraphicsNodes.size() == 1); +// +// } + + protected void makeActions(Graph graph) { + super.makeActions(graph); + exportAction = new ExportAction(this); + importAction = new ImportAction(this); + } + + @Override + protected void fillLocalPullDown() { + super.fillLocalPullDown(); + MenuTools.getOrCreate(getMenuID(),"Model", menuManager).add(exportAction); + MenuTools.getOrCreate(getMenuID(),"Model", menuManager).add(importAction); + } + + + + /* + * These are used for updating CSG models geometry when internal shapes are moved. Interactive update is not possible + * because recalculation of geometry takes too much time. There are several problems in this method: + * 1. it relies on instanceof check + * 2. when shape is moved, transformations of its children are updated, which causes all + * child geometries to be updated, which is not necessary. We want to update only moved + * shape, since updateAllGemetry method takes care of parents. + * + * TODO : this functionality should be moved to TranslateAction + * TODO : prevent moved shape's children to be updated. + */ + + @Override + public void setCurrentAction(InteractiveAction action) { + if (getCurrentAction() == action) + return; + if (getCurrentAction() != null && getCurrentAction() instanceof TranslateAction) { + runGeometryUpdates(); + } + super.setCurrentAction(action); + } + + private void runGeometryUpdates() { + // now we'll just filter out all parents so that they won't be updated multiple times. + HashSet parents = new HashSet(); + for (CSGShapeNode n : geometryUpdates) { + IGraphicsNode parent = n.getParent(); + if (parent instanceof CSGShapeNode) + parents.add((CSGShapeNode)parent); + } + for (CSGShapeNode n : geometryUpdates) { + if (!parents.contains(n)) + n.updateAllGeometry(); + } + geometryUpdates.clear(); + } + + private HashSet geometryUpdates = new HashSet(); + + private void geometryUpdate(CSGShapeNode shape) { + + if (!(getCurrentAction() instanceof TranslateAction)) { + shape.updateAllGeometry(); + } else { + geometryUpdates.add(shape); + } + } + + public Graph createParameterization(Graph g) { + if (isParameterized) { + ContextGraph graph; + if (!(g instanceof ContextGraph)) { + graph = new ContextGraph(g); + graph.setContext(model); + } else { + graph = (ContextGraph)g; + } + Solver solver = new Solver(); + Collection parameters = getModel(graph).getRelatedProperties(ShapeEditorResources.g3dResource.HasSizingParameter); + for (org.simantics.layer0.utils.Property p : parameters) { + IEntity t = EntityFactory.create(graph, p.getResource()); + Collection exp = t.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget); + if (exp.size() > 0) { + Iterator i = exp.iterator(); + while (i.hasNext()) + solver.evaluate(i.next()); + } else { + ErrorLogger.defaultLogWarning("Model property " + p + " is not bound to a expression", null); + } + } + solver.pushToGraph(graph); + return graph; + } else { + return g; + } + } + + + + protected class ShapeEditorAdapter extends ScenegraphAdapterImpl { + + public ShapeEditorAdapter(Session session,JmeRenderingComponent component) { + super(session,component); + } + + @Override + public synchronized void updateGeometry(Graph graph) { + if (isParameterized) { + graph = createParameterization(graph); + } + super.updateGeometry(graph); + } + + + + protected AbstractGraphicsNode instantiateNode(IGraphicsNode comp, + G3DNode node) { + CSGShapeNode mo = new CSGShapeNode(ShapeEditorBase.this, comp, node.getGraph(),node.getResource()); + updateGeometry(mo); + return mo; + } + + + private class ShapeEditorScenegraphQuery extends ScenegraphQuery { + + public ShapeEditorScenegraphQuery(Resource nodeResource) { + super(nodeResource); + } + + @Override + public void shapeAdded(Graph graph,IGraphicsNode n) { + updateGeometry((CSGShapeNode) n); + + if (n.getG3DNode(graph).getParent() == null) { + if (DEBUG)System.out.println("ShapeSubnodeListener " + + n.getResource() + + " has no parent"); + return; + } + if (DEBUG) System.out.print("ShapeSubnodeListener " + n.getResource()); + if (n.getG3DNode(graph).getRelatedObjects(ShapeEditorResources.g3dResource.GeometryDefinitionOf).size() == 0) { + if (DEBUG) System.out.println(" visible"); + ((ISelectableNode)n).setVisible(true); + } else { + if (DEBUG) System.out.println(" invisible"); + ((ISelectableNode)n).setVisible(false); + } + } + +// @Override +// public NodeQuery instantiateQuery(Resource node) { +// return new ShapeEditorScenegraphQuery(node); +// } + } + + @Override + protected ScenegraphQuery newSubnodeListener(G3DNode node) { + return new ShapeEditorScenegraphQuery(node.getResource()); + } + + private class ShapeEditorNodePropertyQuery extends NodePropertyQuery { + public ShapeEditorNodePropertyQuery(Resource nodeResource) { + super(nodeResource); + } + + @Override + public void shapeUpdated(Graph graph,final IGraphicsNode shape) { + if (DEBUG) System.out.println("Tri - Shape id " + shape + " modified"); + ((CSGShapeNode) shape).updateAllGeometry(); + } + +// @Override +// public NodeQuery instantiateQuery(Resource node) { +// return new ShapeEditorNodePropertyQuery(node); +// } + } + + @Override + protected NodePropertyQuery newPropertyListener(G3DNode node) { + return new ShapeEditorNodePropertyQuery(node.getResource()); + } + + private class ShapeEditorNodeTransformationQuery extends NodeTransformationQuery { + public ShapeEditorNodeTransformationQuery(Resource nodeResource) { + super(nodeResource); + } + + @Override + public void shapeUpdated(Graph graph,final IGraphicsNode shape) { + if (DEBUG) System.out.println("Tra - Shape id " + shape + " modified"); + ((CSGShapeNode) shape).updateTransform(graph); + geometryUpdate((CSGShapeNode)shape); + } + +// @Override +// public NodeQuery instantiateQuery(Resource node) { +// return new ShapeEditorNodePropertyQuery(node); +// } + } + + @Override + protected NodeTransformationQuery newTransformationListener(G3DNode node) { + return new ShapeEditorNodeTransformationQuery(node.getResource()); + } + + private class ShapeEditorRootPropertyQuery extends NodePropertyQuery { + public ShapeEditorRootPropertyQuery(Resource nodeResource) { + super(nodeResource); + } + + @Override + public void shapeUpdated(Graph graph, final IGraphicsNode shape) { + if (DEBUG)System.out.println("Tri - Shape id " + shape + " modified"); + + updateParameterizationStatus(graph); + if (isParameterized) { + for (IGraphicsNode n : getNodes()) + if (n instanceof IGeometryNode) + updateGeometry((IGeometryNode) n); + } + } + +// @Override +// public NodeQuery instantiateQuery(Resource node) { +// return new ShapeEditorRootPropertyQuery(node); +// } + } + + @Override + protected NodePropertyQuery newRootPropertyListener(G3DNode root) { + return new ShapeEditorRootPropertyQuery(root.getResource()); + } + + } + + protected void contributeStatusBar(IStatusLineManager manager) { + } + + /** + * Loads the initial scene: all further updates to the view are done by + * listening changes in the shapes and int the shape group + * + * @param resource + */ + protected void reloadFrom(IEntity thing) { + if (model != null) { + throw new UnsupportedOperationException( + "Reloading instantiated viewer not supported"); + + } + if (thing.isInstanceOf(ShapeEditorResources.csgResource.CSGModel)) { + //System.out.print("ShapeEditorView.reloadFrom() : model"); + Graph g = thing.getGraph(); + model = thing.getResource(); + //System.out.println(" " + model.getResource()); + adapter.setRootNode(new G3DNode(thing)); + updateParameterizationStatus(g); + + //loadGroup(thing.getGraph()); + + } else { + throw new UnsupportedOperationException("Cannot load ShapeViewer for Resource:" + thing); + } + + } + + private void updateParameterizationStatus(Graph graph) { + G3DModel model = getModel(graph); + if(model.getRelatedObjects(ShapeEditorResources.g3dResource.HasSizingParameter).size() > 0) { + isParameterized = true; + } else { + isParameterized = false; + } + parent.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { +// for (Action a : addActions) +// a.setEnabled(!isParameterized); +// unionAction.setEnabled(!isParameterized); +// differenceAction.setEnabled(!isParameterized); +// intersectionAction.setEnabled(!isParameterized); +// linkAction.setEnabled(!isParameterized); +// unlinkAction.setEnabled(!isParameterized); +// translateAction.setEnabled(!isParameterized); +// rotateAction.setEnabled(!isParameterized); +// removeAction.setEnabled(!isParameterized); + } + + }); + } + + public Resource getModelResource() { + return model; + } + + public G3DModel getModel(Graph graph) { + return new G3DModel(graph, model); + } + + @Override + protected SelectionAdapter createSelectionAdapter() { + return new ShapeEditorSelectionAdapter(adapter); + } + + protected class ShapeEditorSelectionAdapter extends SelectionAdapter { + + public ShapeEditorSelectionAdapter(ScenegraphAdapter adapter) { + super(adapter); + } + + public void setEditorSelection() { + List sel = getSelectedObjects(); + for (IGraphicsNode o : adapter.getNodes()) + if (o instanceof ISelectableNode) { + ISelectableNode n = (ISelectableNode)o; + if (sel.contains(o)) + n.setSelected(true); + else + n.setSelected(false); + } + List selected = getSelectedResources(); + for (Resource r : selected) { + if (!adapter.hasNode(r)) { + //adapter.addInbound(r).setSelected(true); + } + } + } + + public void setEditorHighlightSelection() { + List sel = getInteractiveSelectedObjects(); + for (IGraphicsNode o : adapter.getNodes()) + if (o instanceof CSGShapeNode) { + if (sel.contains(o)) + ((CSGShapeNode) o).setHighlighted(true); + else + ((CSGShapeNode) o).setHighlighted(false); + } + } + + public void setEditorSelection(boolean addShapes) { + + List sel = getSelectedObjects(); + for (IGraphicsNode o : adapter.getNodes()) + if (o instanceof ISelectableNode) { + ISelectableNode n = (ISelectableNode)o; + if (sel.contains(o)) + n.setSelected(true); + else + n.setSelected(false); + } + viewChanged = true; + if (addShapes) { + session.syncRead(new GraphRequestAdapter() { + @Override + public GraphRequestStatus perform(Graph g) throws Exception { + List selected = getSelectedResources(); + for (Resource r : selected) { + if (!adapter.hasNode(r)) { + IEntity t = EntityFactory.create(g, r); + if (t.isInstanceOf(ShapeEditorResources.g3dResource.Shape)) { + G3DNode group = G3DTools.getModelFromResource(g,r); + if (group != null + && group.getResource().equals(model.getResource())) { + //adapter.addInbound(g).setSelected(true); + } + + } + } + } + return GraphRequestStatus.transactionComplete(); + } + }); + + } + } + + public StructuredResourceSelection filterSelection(ISelection selection) { + if (!(selection instanceof StructuredResourceSelection)) + return new StructuredResourceSelection(); + return (StructuredResourceSelection) selection; + } + + } + + /** + * Receives selection changes + * + * @param part + * @param selection + */ + protected void pageSelectionChanged(IWorkbenchPart part, ISelection selection) { + + StructuredResourceSelection s = SelectionAdapter.transformSelection(selection); + //System.out.println("ShapeEditorBase.pageSelectionChanged " + s); + selectionAdapter.setCurrentSelection(s); + + if (!(part instanceof ThreeDimensionalEditorProvider)) { + ((ShapeEditorSelectionAdapter) selectionAdapter).setEditorSelection(true); + return; + } + ThreeDimensionalEditorBase e = ((ThreeDimensionalEditorProvider)part).getEditor(); + if (!(e instanceof ShapeEditorBase)) { + ((ShapeEditorSelectionAdapter) selectionAdapter).setEditorSelection(true); + return; + } + + ShapeEditorBase editor = (ShapeEditorBase)e; + + if (!editor.getModelResource().equals(model.getResource())) { + selectionAdapter.setCurrentSelection(new StructuredResourceSelection()); + ((ShapeEditorSelectionAdapter) selectionAdapter).setEditorSelection(false); + return; + } + selectionAdapter.setEditorSelection(); + } + + @Override + protected void hookDragAndDrop() { + super.hookDragAndDrop(); + dropTarget.addDropListener(new DropListener() { + public boolean acceptDrop(StructuredResourceSelection s, Resource[] ids) { + if (!s.isEmpty()) + return false; + if (ids == null) + return false; + if (ids.length != 1) + return false; + final Resource r = ids[0]; + GraphRequestWithResult rq = new GraphRequestWithResult() { + @Override + public Boolean performWithResult(Graph g) throws Exception { + IEntity t = EntityFactory.create(g, r); + return t.isInstanceOf(ShapeEditorResources.csgResource.Primitive); + } + }; + session.syncRead(rq); + return rq.getResult(); + } + + public void doDrop(StructuredResourceSelection s, Resource[] ids) { + session.asyncWrite(new GraphRequestAdapter() { + Resource r; + + public GraphRequestStatus perform(Graph g) throws Exception { + IEntity type = EntityFactory.create(g); + IEntity instance = type.instantiate(); + Shape shape = new Shape(instance); + resetShape(shape); + CSGModel m = new CSGModel(g, model); + m.getChild().add(shape.toG3DNode()); // FIXME : stubcast + return GraphRequestStatus.transactionComplete(); + + }; + + @Override + public void requestCompleted(GraphRequestStatus status) { + selectionAdapter + .updateSelection(new StructuredResourceSelection(r)); + super.requestCompleted(status); + } + } + ); + + } + }); + } + + private void resetShape(Shape shape) { + G3DTools.resetTransformation(shape); + Graph graph = shape.getGraph(); + if (shape.isInstanceOf(ShapeEditorResources.csgResource.Primitive)) { + Primitive prim = new Primitive(shape); + Collection c = prim.getSizingProperty(); + if (c.size() == 0) + ErrorLogger.getDefault().logWarning("Shape does not contain sizing properties.", null); + + for (Property p : c) { + if (p.isInstanceOf(graph.getBuiltins().Double)) { + graph.setScalarDouble(p.getResource(), 1.0); + } else if (p.isInstanceOf(graph.getBuiltins().Integer)) { + graph.setScalarInteger(p.getResource(), 1); + } else { + ErrorLogger.getDefault().logWarning("Cannot handle sizing property " + p.getName() , null); + } + } + } + + } + + @Override + public Object getAdapter(Class adapter) { + if (adapter == IContentOutlinePage.class) { + if (getModelResource() == null) + return null; + final StructureOutlinePage page = new StructureOutlinePage(sessionContext,getModelResource()); + + getSelectionAdapter().addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + page.setSelection(event.getSelection()); + + } + }); + parent.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + page.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + selectionAdapter.setSelection(SelectionAdapter.transformSelection(event.getSelection())); + } + }); + } + }); + + + + return page; + } + return null; + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorView.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorView.java new file mode 100644 index 00000000..8fa7a37b --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/ShapeEditorView.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.views; + +import org.simantics.db.management.ISessionContext; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; +import org.simantics.proconf.g3d.base.ThreeDimensionalEditorPart; + + + + +/** + * Shape Editor / CGS-modeling + * + * + * @author Marko Luukkainen + * + */ +public class ShapeEditorView extends ThreeDimensionalEditorPart { + + + @Override + protected ThreeDimensionalEditorBase createEditor(ISessionContext session) { + return new ShapeEditorBase(session); + } + +} + diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureOutlinePage.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureOutlinePage.java new file mode 100644 index 00000000..c0ddb2af --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureOutlinePage.java @@ -0,0 +1,21 @@ +package org.simantics.proconf.g3d.shapeeditor.views; + +import org.simantics.db.Resource; +import org.simantics.db.management.ISessionContext; +import org.simantics.layer0.utils.viewpoints.ResourceViewpoint; +import org.simantics.proconf.browsing.views.GraphExplorerOutlinePage; +import org.simantics.proconf.g3d.shapeeditor.common.ViewpointGenerator; + +public class StructureOutlinePage extends GraphExplorerOutlinePage { + + + public StructureOutlinePage(ISessionContext session, Resource model) { + super(session,model); + } + + @Override + public ResourceViewpoint getViewPoint(ISessionContext sessionContext) { + return ViewpointGenerator.createObjectStructureViewpoint(); + } + +} diff --git a/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureView.java b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureView.java new file mode 100644 index 00000000..f747d49c --- /dev/null +++ b/org.simantics.proconf.g3d.shapeeditor/src/org/simantics/proconf/g3d/shapeeditor/views/StructureView.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.shapeeditor.views; + +import org.simantics.db.management.ISessionContext; +import org.simantics.layer0.utils.viewpoints.ResourceViewpoint; +import org.simantics.proconf.browsing.views.GraphExplorerView; +import org.simantics.proconf.g3d.shapeeditor.common.ViewpointGenerator; + +public class StructureView extends GraphExplorerView { + + @Override + protected void contributeActions() { + } + + @Override + protected ResourceViewpoint getViewpoint(ISessionContext context) { + return ViewpointGenerator.createStuctureViewpoint(); + } + + /* + @Override + public String getContributorId() { + return "fi.vtt.simantics.shapeeditor.pcid"; + } + + @Override + public Object getAdapter(Class adapter) { + if (adapter == IPropertySheetPage.class) { + return new TabbedPropertySheetPage(this); + } + return super.getAdapter(adapter); + } + */ + +} -- 2.45.2