Skip to content

Commit b0ad6fa

Browse files
Merge pull request #34 from mastodon-sc/optional_time_scaling
Add Optional time scaling for Blender Interactive
2 parents e3a4de2 + 097fc56 commit b0ad6fa

5 files changed

Lines changed: 104 additions & 21 deletions

File tree

src/main/java/org/mastodon/blender/Blender3dViewPlugin.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.mastodon.app.ui.ViewMenuBuilder;
3232
import org.mastodon.blender.csv.ExportGraphAsCsvAction;
3333
import org.mastodon.blender.csv.StartBlenderWithCsvAction;
34+
import org.mastodon.blender.interactive.BlenderInteractiveCommand;
3435
import org.mastodon.blender.setup.BlenderSettingsCommand;
3536
import org.mastodon.blender.setup.BlenderSetup;
3637
import org.mastodon.mamut.KeyConfigScopes;
@@ -187,17 +188,8 @@ private void updateEnabledActions()
187188

188189
private void startBlenderView()
189190
{
190-
if ( projectModel != null )
191-
{
192-
new Thread(() -> {
193-
try {
194-
new BlenderController( projectModel );
195-
}
196-
catch ( StartBlenderException e ) {
197-
BlenderSetup.startSetupWithMessage( context, e );
198-
}
199-
}).start();
200-
}
191+
context.service( CommandService.class ).run( BlenderInteractiveCommand.class, true, "projectModel", projectModel,
192+
"context", projectModel.getContext() );
201193
}
202194

203195
private void startBlenderWithCsv()

src/main/java/org/mastodon/blender/BlenderController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@ public class BlenderController
8484

8585
int known_active_object = -1;
8686

87-
public BlenderController( ProjectModel projectModel ) {
87+
public BlenderController( ProjectModel projectModel, int timeScalingFactor )
88+
{
8889
this.projectModel = projectModel;
8990
this.model = projectModel.getModel();
9091
this.groupHandle = projectModel.getGroupManager().createGroupHandle();
9192
this.groupHandle.setGroupId( -1 );
9293
NavigationHandler<Spot, Link> navigationModel = groupHandle.getModel( projectModel.NAVIGATION );
9394
this.focusModel = new AutoNavigateFocusModel<>( projectModel.getFocusModel(), navigationModel );
9495
this.timePointModel = groupHandle.getModel( projectModel.TIMEPOINT );
95-
this.client = new ViewServiceClient( projectModel.getContext(), new ViewServiceListener() );
96+
this.client = new ViewServiceClient( projectModel.getContext(), new ViewServiceListener(), timeScalingFactor );
9697
sendCoordinates();
9798
sendColors();
9899
sendTagSetList();

src/main/java/org/mastodon/blender/ViewServiceClient.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public class ViewServiceClient
6565
* Mapping a timepoint to multiple frames in Blender has the advantage
6666
* that the Blender automatically interpolates between the timepoints.
6767
**/
68-
private static final int TIME_SCALING_FACTOR = 10;
68+
private static final int DEFAULT_TIME_SCALING_FACTOR = 10;
6969

7070
public static final String URL = "localhost:";
7171

@@ -75,6 +75,8 @@ public class ViewServiceClient
7575

7676
private final Listener listener;
7777

78+
private final int timeScalingFactor;
79+
7880
public static void waitForConnection( int port )
7981
{
8082
ManagedChannel channel = ManagedChannelBuilder.forTarget( URL + port ).usePlaintext().build();
@@ -111,14 +113,22 @@ public static void closeBlender( int port )
111113
}
112114

113115
public ViewServiceClient( final Context context, final Listener listener )
116+
{
117+
this( context, listener, DEFAULT_TIME_SCALING_FACTOR );
118+
}
119+
120+
public ViewServiceClient( final Context context, final Listener listener, final int timeScalingFactor )
114121
{
115122
this.listener = listener;
123+
this.timeScalingFactor = timeScalingFactor;
116124
int port = StartBlender.getFreePort();
117-
try {
125+
try
126+
{
118127
StartBlender.startBlender( context, port );
119128
}
120-
catch( Throwable throwable ) {
121-
throw new StartBlenderException(throwable);
129+
catch ( Throwable throwable )
130+
{
131+
throw new StartBlenderException( throwable );
122132
}
123133
ManagedChannel channel = ManagedChannelBuilder.forTarget( URL + port ).usePlaintext().build();
124134
Runtime.getRuntime().addShutdownHook( new Thread( channel::shutdown ) );
@@ -135,7 +145,7 @@ public int receiveSyncGroupIndex()
135145

136146
public int receiveTimepoint()
137147
{
138-
return Math.round( ( float ) blockingStub.getTimePoint( Empty.newBuilder().build() ).getTimePoint() / TIME_SCALING_FACTOR );
148+
return Math.round( ( float ) blockingStub.getTimePoint( Empty.newBuilder().build() ).getTimePoint() / timeScalingFactor );
139149
}
140150

141151
public int receiveActiveSpotId()
@@ -169,7 +179,7 @@ public void sendTimepoint( int timePoint )
169179
{
170180
//System.out.println("Mastodon -> Blender: set time point to " + timePoint);
171181
blockingStub.setTimePoint( SetTimePointRequest.newBuilder()
172-
.setTimepoint( timePoint * TIME_SCALING_FACTOR )
182+
.setTimepoint( timePoint * timeScalingFactor )
173183
.build() );
174184
}
175185

@@ -238,7 +248,7 @@ private void coordinates( AddMovingSpotRequest.Builder request, Spot spot, Affin
238248
request.addCoordinates( point.getFloatPosition( 0 ) );
239249
request.addCoordinates( point.getFloatPosition( 1 ) );
240250
request.addCoordinates( point.getFloatPosition( 2 ) );
241-
request.addTimepoints( spot.getTimepoint() * TIME_SCALING_FACTOR );
251+
request.addTimepoints( spot.getTimepoint() * timeScalingFactor );
242252
}
243253

244254
// callback
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package org.mastodon.blender.interactive;
2+
3+
import org.mastodon.blender.BlenderController;
4+
import org.mastodon.blender.StartBlenderException;
5+
import org.mastodon.blender.setup.BlenderSetup;
6+
import org.mastodon.mamut.ProjectModel;
7+
import org.scijava.Cancelable;
8+
import org.scijava.Context;
9+
import org.scijava.Initializable;
10+
import org.scijava.ItemVisibility;
11+
import org.scijava.command.Command;
12+
import org.scijava.plugin.Parameter;
13+
import org.scijava.plugin.Plugin;
14+
15+
/**
16+
* This dialog allows the user to set the time scaling factor for Blender Interactive view.
17+
*/
18+
@Plugin( type = Command.class, name = "Set time scaling for Blender Interactive View" )
19+
public class BlenderInteractiveCommand implements Command, Initializable, Cancelable
20+
{
21+
22+
@Parameter
23+
private Context context;
24+
25+
@Parameter
26+
private ProjectModel projectModel;
27+
28+
@Parameter( visibility = ItemVisibility.MESSAGE ) // Text that is displayed in the dialog and never changes.
29+
private final String description = "<html>"
30+
+ "\n<body width=10cm align=left>"
31+
+ "\nA time scaling factor of 1 means that there is no time scaling and the frame number in Big Data View / TrackScheme views matches the frame number in Blender.<br><br>"
32+
+ "\nA Time scaling factor larger than 1 means that interpolation between frames in the Blender view is computed, which leads to a smoother animation."
33+
+ "\nFrame numbers in Blender are then multiplied by the time scaling factor."
34+
+ "\n</body>"
35+
+ "\n</html>";
36+
37+
@Parameter( label = "Time scaling factor", description = "1 means no time scaling. Larger means leads to time scaling and interpolation.", min = "1" )
38+
private int timeScalingFactor = 1;
39+
40+
@Override
41+
public void run()
42+
{
43+
startBlenderView();
44+
}
45+
46+
@Override
47+
public boolean isCanceled()
48+
{
49+
return false;
50+
}
51+
52+
@Override
53+
public void cancel( String reason )
54+
{
55+
// The goal is to have a cancel button in the dialog. This method does not need to do anything to achieve that.
56+
}
57+
58+
@Override
59+
public String getCancelReason()
60+
{
61+
return null;
62+
}
63+
64+
private void startBlenderView()
65+
{
66+
if ( projectModel != null )
67+
{
68+
new Thread( () -> {
69+
try
70+
{
71+
new BlenderController( projectModel, timeScalingFactor );
72+
}
73+
catch ( StartBlenderException e )
74+
{
75+
BlenderSetup.startSetupWithMessage( context, e );
76+
}
77+
} ).start();
78+
}
79+
}
80+
}

src/test/java/StartBlenderAndMastodon.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static void main( String... args ) throws IOException
4545
{
4646
copyAddonFromRepoToBlender();
4747
ProjectModel projectModel = MastodonUtils.showGui( "/home/arzt/Datasets/DeepLineage/Johannes/2022-07-27_NL46xNL22_eachview_2023-07-04_cleaned.mastodon" );
48-
new BlenderController( projectModel );
48+
new BlenderController( projectModel, 1 );
4949
}
5050

5151
private static void copyAddonFromRepoToBlender() throws IOException

0 commit comments

Comments
 (0)