Sample

Schnappinger/aoi/artofillusion.animation.AnimationPreviewer

Human rating uses the original dataset scale.

Human2.03
Lines301

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
16.4Δ 9.5
Scalabrino0.6350–1; higher is more readable
27.4Δ 20.5
Dorn0.0460–1; higher is more readable
28.4Δ 21.5
Mi0.7190–1; higher is more readable
86.5Δ 79.5
LLOC153Logical lines; fewer is more readable
17.8Δ 10.9
DeepSeek V4 Pro150–20; mean of three runs
38.0Δ 31.0
GPT-6.1 Sol13.330–20; mean of three runs
12.2Δ 5.3
BTTF0.1780–1; higher is more readable
9.6Δ 2.6
Human2.031–4; original rating
6.9

Views

Source code

/* Copyright (C) 2001-2012 by Peter Eastman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package artofillusion.animation; import artofillusion.*; import artofillusion.object.*; import artofillusion.ui.*; import artofillusion.view.*; import buoy.event.*; import buoy.widget.*; import java.awt.*; import java.awt.image.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.text.*; import javax.imageio.ImageIO; /** This class generates a wireframe preview of an animation. */ public class AnimationPreviewer implements Runnable { private LayoutWindow window; private double originalTime; private ValueField widthField, heightField, startField, endField, fpsField; private BLabel timeLabel, frameLabel; private Scene theScene; private ObjectInfo sceneCamera; private BComboBox camChoice, modeChoice; private SceneViewer canvas; private Thread previewThread; private BDialog display; private byte imageData[][]; private NumberFormat format; static int currentCamera = 0, width = 320, height = 240, fps = 15, mode = 2; static double startTime = 0.0, endTime = 1.0; public AnimationPreviewer(LayoutWindow parent) { window = parent; theScene = window.getScene(); // Find all the cameras in the scene. ObjectInfo obj; int i, count; for (i = 0, count = 0; i < theScene.getNumObjects(); i++) { obj = theScene.getObject(i); if (obj.getObject() instanceof SceneCamera) count++; } if (count == 0) { new BStandardDialog("", Translate.text("noCameraError"), BStandardDialog.INFORMATION).showMessageDialog(window); return; } if (count <= currentCamera) currentCamera = 0; ObjectInfo cameras[] = new ObjectInfo [count]; for (i = 0, count = 0; i < theScene.getNumObjects(); i++) { obj = theScene.getObject(i); if (obj.getObject() instanceof SceneCamera) cameras[count++] = obj; } // Create the components. camChoice = new BComboBox(); for (i = 0; i < cameras.length; i++) camChoice.add(cameras[i].getName()); camChoice.setSelectedIndex(currentCamera); modeChoice = new BComboBox(new Object [] { Translate.text("menu.wireframeDisplay"), Translate.text("menu.shadedDisplay"), Translate.text("menu.smoothDisplay"), Translate.text("menu.texturedDisplay"), Translate.text("menu.transparentDisplay") }); modeChoice.setSelectedIndex(mode); widthField = new ValueField((double) width, ValueField.POSITIVE+ValueField.INTEGER); heightField = new ValueField((double) height, ValueField.POSITIVE+ValueField.INTEGER); startField = new ValueField(startTime, ValueField.NONE); endField = new ValueField(endTime, ValueField.NONE); fpsField = new ValueField(fps, ValueField.POSITIVE+ValueField.INTEGER); // Display a dialog with the various options. ComponentsDialog dlg = new ComponentsDialog(window, Translate.text("renderPreview"), new Widget [] {camChoice, modeChoice, startField, endField, widthField, heightField, fpsField}, new String [] {Translate.text("Camera"), Translate.text("menu.displayMode"), Translate.text("StartTime"), Translate.text("EndTime"), Translate.text("Width"), Translate.text("Height"), Translate.text("FramesPerSec")}); if (!dlg.clickedOk()) return; currentCamera = camChoice.getSelectedIndex(); sceneCamera = cameras[currentCamera]; mode = modeChoice.getSelectedIndex(); width = (int) widthField.getValue(); height = (int) heightField.getValue(); startTime = startField.getValue(); endTime = endField.getValue(); fps = (int) fpsField.getValue(); originalTime = theScene.getTime(); // Display a dialog to show the preview. display = new BDialog(window, Translate.text("Preview"), true); format = NumberFormat.getNumberInstance(); format.setMaximumFractionDigits(3); ColumnContainer content = new ColumnContainer(); display.setContent(BOutline.createEmptyBorder(content, UIUtilities.getStandardDialogInsets())); content.setDefaultLayout(new LayoutInfo(LayoutInfo.WEST, LayoutInfo.HORIZONTAL, new Insets(2, 0, 2, 0), null)); content.add(timeLabel = new BLabel()); content.add(frameLabel = new BLabel()); setLabels(0.0, 0); content.add(canvas = new SceneViewer(theScene, new RowContainer(), parent, true)); canvas.setPreferredSize(new Dimension(AnimationPreviewer.width, AnimationPreviewer.height)); canvas.setRenderMode(mode); canvas.setBoundCamera(sceneCamera); canvas.setPerspective(true); canvas.setTool(new EditingTool(parent) { public boolean hilightSelection() { return false; } }); content.add(Translate.button("close", this, "doClose"), new LayoutInfo()); display.pack(); UIUtilities.centerDialog(display, window); display.setResizable(false); previewThread = new Thread(this); previewThread.setPriority(Thread.NORM_PRIORITY-1); previewThread.start(); display.setVisible(true); } /** Generate and display all of the frames in a loop. */ public void run() { int totalFrames = (int) Math.ceil((endTime-startTime)*fps); if (totalFrames <= 0) totalFrames = 1; imageData = new byte [totalFrames][]; Camera cam = canvas.getCamera(); long lastUpdate = 0L, ms, delay = 1000/fps; // In the first loop, we render all of the images. try { for (int i = 0; i < totalFrames; i++) { final double time = startTime+i/(double) fps; theScene.setTime(time); SceneCamera sc = (SceneCamera) sceneCamera.getObject(); cam.setCameraCoordinates(sceneCamera.getCoords().duplicate()); cam.setScreenTransform(sc.getScreenTransform(width, height), width, height); final int frame = i; try { EventQueue.invokeAndWait(new Runnable() { public void run() { setLabels(time, frame); SoftwareCanvasDrawer drawer = (SoftwareCanvasDrawer) canvas.getCanvasDrawer(); Graphics2D canvasGraphics = (Graphics2D) canvas.getComponent().getGraphics(); drawer.paint(new RepaintEvent(canvas, canvasGraphics)); canvasGraphics.dispose(); imageData[frame] = recordImage(drawer.getImage()); } }); } catch (Exception ex) { return; } if (Thread.currentThread().isInterrupted()) return; ms = System.currentTimeMillis(); if (ms < lastUpdate+delay) { try { Thread.sleep(lastUpdate+delay-ms); } catch (InterruptedException ex) { return; } } lastUpdate = System.currentTimeMillis(); } // In later loops, we simply retrieve the data from the array. while (!Thread.currentThread().isInterrupted()) { for (int i = 0; i < totalFrames; i++) { final double time = startTime+i/(double) fps; final int frame = i; final Image image = retrieveImage(imageData[i]); try { EventQueue.invokeAndWait(new Runnable() { public void run() { setLabels(time, frame); Graphics2D canvasGraphics = (Graphics2D) canvas.getComponent().getGraphics(); canvasGraphics.drawImage(image, 0, 0, null); canvasGraphics.dispose(); } }); } catch (Exception ex) { return; } ms = System.currentTimeMillis(); if (ms < lastUpdate+delay) { try { Thread.sleep(lastUpdate+delay-ms); } catch (InterruptedException ex) { return; } } lastUpdate = System.currentTimeMillis(); } } } catch (IOException ex) { ex.printStackTrace(); } } /** Close the window. */ private void doClose() { previewThread.interrupt(); try { previewThread.join(); } catch (InterruptedException ex) { } theScene.setTime(originalTime); display.dispose(); } /** Set the labels for the current time and frame. */ private void setLabels(double time, int frame) { timeLabel.setText(Translate.text("Time")+": "+format.format(time)); frameLabel.setText(Translate.text("Frame")+": "+(frame+1)); } /** Record the bitmap for an image. */ private byte [] recordImage(BufferedImage image) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "png", baos); return baos.toByteArray(); } catch (IOException ex) { return null; } } /** Copy a bitmap into the image. */ private Image retrieveImage(byte bytes[]) throws IOException { return ImageIO.read(new ByteArrayInputStream(bytes)); } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.13527.709−446.414
Source linesThe number of non-empty source lines.301+120.4
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.752−7.128

Intercept 8.87 + feature contributions = -324.272 (log-odds).
Score = sigmoid(-324.272) = 0.

Score0.635

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.301−9.621
Indentation frequencyHow rapidly indentation changes from line to line.287+9.19
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.287−6.165
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.299.933+3.783
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.117.937−1.33
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.117.987+1.099
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.102−0.05

Intercept 0.07 + feature contributions = -3.024 (log-odds).
Score = sigmoid(-3.024) = 0.046.

Score0.719
Score153
Run 1

The code is generally readable and well-structured, with clear sections and Javadoc comments explaining the main phases. It uses a class-based approach with logical field grouping and helper methods, and the action granularity is mostly good—each line does one thing. However, several issues reduce readability. Nesting is deep in places, especially in the `run()` method, where nested try-catch blocks and anonymous inner classes obscure the flow. The `run()` method is too long and mixes concerns like rendering, timing, and UI updates, making the reading flow disorganized. Some magic numbers and repeated code blocks (e.g., timing and sleep logic) add unnecessary length and reduce clarity of intent. Also, the constructor has multiple responsibilities, from camera discovery to UI setup, which could be better separated. Overall, the code is above average but could be significantly improved by extracting methods (e.g., for frame rendering, delay handling) and flattening nested structures.

Run 2

The code is generally organized into clear sections (e.g., camera discovery, UI setup, rendering loop) with descriptive method names and comments. However, the constructor is quite long and performs multiple responsibilities: finding cameras, building the dialog, and setting up the preview. The run() method contains deeply nested loops, anonymous inner classes, and duplicated frame-timing logic, which hurts readability. Some lines combine multiple actions, particularly in loop headers and UI setup. Variable declarations are interspersed with logic, and magic numbers or implicit defaults appear. The reading flow is acceptable but could be improved by extracting methods such as 'collectCameras()', 'buildOptionsDialog()', 'renderFrame()', and 'waitForNextFrame()'. Overall, the code is understandable but not as flat or single-purpose as it could be.

Run 3

The code demonstrates excellent readability through clear method separation, descriptive naming, and consistent formatting. Each method has a single, well-defined responsibility (e.g., recordImage, retrieveImage, setLabels), keeping actions granular. The constructor is logically organized into distinct sections with helpful comments (finding cameras, creating components, displaying dialogs). Nesting is moderate - the run() method contains nested loops and inner classes for threading, which adds some complexity but remains understandable given the nature of animation preview generation. The flow is mostly natural: setup leads to dialog display, then thread execution with clear render-and-display logic. Minor deductions come from the deeply nested anonymous inner classes within run() and some duplicated sleep/delay patterns between the two loops, which could be extracted into a helper method. The long constructor also slightly impacts readability, though sections are well-demarcated. Overall, the code is clear, well-structured, and maintainable, with only minor opportunities for refactoring the timing logic and reducing nesting depth.

Run 1

Code Structure: Responsibilities are grouped into clearly named methods, but the constructor combines camera discovery, configuration, UI construction, and thread startup; run() mixes rendering, playback, and timing. Nesting: Rendering and playback contain deep nesting through loops, try/catch blocks, conditionals, and anonymous callbacks. Clarity of intent: Descriptive method names and section comments explain the workflow, although terse variables, numeric display modes, shared mutable state, and silently handled exceptions obscure details. Code length: The class is moderately long, with duplicated camera scans, timing logic, and UI-update patterns that could be extracted. Action granularity: Most statements perform one action, but assignments embedded in calls, grouped declarations, and counter increments inside indexing reduce clarity. Reading flow: The configuration-to-rendering-to-playback sequence is natural and formatting is consistent, but long methods and nested asynchronous operations require substantial context tracking.

Run 2

Code Structure: Methods separate closing, labeling, and image serialization, but the constructor combines camera discovery, configuration, UI construction, and thread startup; run() combines rendering and playback. Nesting: Rendering and playback contain deeply nested loops, try/catch blocks, and anonymous Runnable implementations. Clarity of intent: Descriptive names and section comments explain the workflow, although terse variables and silent exception handling obscure details. Code length: The lengthy constructor and duplicated frame timing and UI-update logic could be extracted into helpers. Action granularity: Most lines perform one action, but grouped declarations, assignments within calls, and count increments within array indexing reduce clarity. Reading flow: The overall configuration-to-rendering-to-playback sequence is logical, with useful whitespace and comments, but concurrency callbacks and repeated error-handling blocks interrupt the flow.

Run 3

Code Structure: Comments divide the workflow into logical stages, and small helpers isolate labeling and image conversion, but the constructor and run() combine too many responsibilities. Nesting: Rendering and playback contain deeply nested loops, try/catch blocks, conditionals, and anonymous Runnable implementations. Clarity of intent: Most names and comments explain the animation-preview process, though abbreviated variables and silent exception handling obscure details. Code length: The class is moderately long, with duplicated timing and UI-update logic that could be extracted into helpers. Action granularity: Most statements perform one action, but combined declarations, assignment inside calls, and loop counter manipulation occasionally increase parsing effort. Reading flow: Setup, initial rendering, cached playback, and cleanup follow a natural sequence; however, lengthy methods, shared mutable fields, and transitions between background execution and UI callbacks make the control flow harder to follow.