Sample

Schnappinger/aoi/artofillusion.animation.IKTrack

Human rating uses the original dataset scale.

Human3
Lines473

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
10.4Δ 14.7
Scalabrino0.6830–1; higher is more readable
34.2Δ 9.2
Dorn0.0030–1; higher is more readable
13.2Δ 11.9
Mi0.7370–1; higher is more readable
89.1Δ 64.0
LLOC261Logical lines; fewer is more readable
9.6Δ 15.5
DeepSeek V4 Pro150–20; mean of three runs
38.0Δ 12.9
GPT-6.1 Sol15.330–20; mean of three runs
30.7Δ 5.6
BTTF0.2020–1; higher is more readable
10.6Δ 14.5
Human31–4; original rating
25.1

Views

Source code

/* Copyright (C) 2003-2013 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.animation.distortion.*; import artofillusion.math.*; import artofillusion.object.*; import artofillusion.ui.*; import buoy.event.*; import buoy.widget.*; import java.io.*; import java.util.*; /** This is a Track which modifies the shape of an object using inverse kinematics. */ public class IKTrack extends Track { private ObjectInfo info; private Vector constraints; private boolean useGestures; private WeightTrack theWeight; public IKTrack(ObjectInfo info) { super("Inverse Kinematics"); this.info = info; theWeight = new WeightTrack(this); constraints = new Vector(); useGestures = true; } /** Get whether to reshape the mesh based on its gestures. */ public boolean getUseGestures() { return useGestures; } /** Set whether to reshape the mesh based on its gestures. */ public void setUseGestures(boolean use) { useGestures = use; } /** This method presents a window in which the user can edit the track. */ public void edit(LayoutWindow win) { if (info.getSkeleton() == null) new BStandardDialog("", Translate.text("ikNotApplyWarning"), BStandardDialog.INFORMATION).showMessageDialog(win); else new Editor(win); } /** Modify the position of the object. */ public void apply(double time) { double weight = theWeight.getWeight(time); Skeleton skeleton = info.getSkeleton(); if (skeleton == null) return; Joint joint[] = skeleton.getJoints(); if (joint.length == 0) return; boolean locked[] = new boolean [joint.length]; Vec3 target[] = new Vec3 [joint.length]; Mat4 toLocal = info.getCoords().toLocal(); for (int i = 0; i < constraints.size(); i++) { Constraint c = (Constraint) constraints.elementAt(i); int index = skeleton.findJointIndex(c.jointID); if (index == -1) continue; if (c.target == null) locked[index] = true; else { CoordinateSystem coords = c.target.getCoords(); if (coords == null) locked[index] = true; else target[index] = toLocal.times(coords.getOrigin()); } } Actor actor = Actor.getActor(info.getObject()); info.addDistortion(new IKDistortion(locked, target, weight, actor)); } /** Create a duplicate of this track. */ public Track duplicate(Object obj) { IKTrack t = new IKTrack((ObjectInfo) obj); t.name = name; t.enabled = enabled; t.quantized = quantized; t.constraints = new Vector(); for (int i = 0; i < constraints.size(); i++) { Constraint c = (Constraint) constraints.elementAt(i); t.constraints.addElement(c.duplicate()); } t.theWeight = (WeightTrack) theWeight.duplicate(t); return t; } /** Make this track identical to another one. */ public void copy(Track tr) { IKTrack t = (IKTrack) tr; name = t.name; enabled = t.enabled; quantized = t.quantized; constraints = new Vector(); for (int i = 0; i < t.constraints.size(); i++) { Constraint c = (Constraint) t.constraints.elementAt(i); constraints.addElement(c.duplicate()); } theWeight = (WeightTrack) t.theWeight.duplicate(t); } /** Get a list of all keyframe times for this track. */ public double [] getKeyTimes() { return new double [0]; } /** Move a keyframe to a new time, and return its new position in the list. */ public int moveKeyframe(int which, double time) { return -1; } /** Delete the specified keyframe. */ public void deleteKeyframe(int which) { } /** This track is null if it has no targets. */ public boolean isNullTrack() { for (int i = 0; i < constraints.size(); i++) if (((Constraint) constraints.elementAt(i)).target != null) return false; return true; } /** This has a single child track. */ public Track [] getSubtracks() { return new Track [] {theWeight}; } /** Determine whether this track can be added as a child of an object. */ public boolean canAcceptAsParent(Object obj) { return (obj instanceof ObjectInfo && ((ObjectInfo) obj).getObject() instanceof Mesh); } /** Get the parent object of this track. */ public Object getParent() { return info; } /** Set the parent object of this track. */ public void setParent(Object obj) { info = (ObjectInfo) obj; } /** Get an array of any objects which this track depends on (and which therefore must be updated before this track is applied). */ public ObjectInfo [] getDependencies() { Vector v = new Vector(); for (int i = 0; i < constraints.size(); i++) { Constraint c = (Constraint) constraints.elementAt(i); if (c.target != null) v.addElement(c.target.getObject()); } ObjectInfo ref[] = new ObjectInfo [v.size()]; v.copyInto(ref); return ref; } /** Delete all references to the specified object from this track. This is used when an object is deleted from the scene. */ public void deleteDependencies(ObjectInfo obj) { for (int i = constraints.size()-1; i >= 0; i--) { Constraint c = (Constraint) constraints.elementAt(i); if (c.target != null && c.target.getObject() == obj) constraints.removeElementAt(i); } } public void updateObjectReferences(Map<ObjectInfo, ObjectInfo> objectMap) { for (int i = constraints.size()-1; i >= 0; i--) { Constraint c = (Constraint) constraints.elementAt(i); if (c.target != null && objectMap.containsKey(c.target.getObject())) { ObjectInfo newObject = objectMap.get(c.target.getObject()); if (c.target.getJoint() == null) c.target = new ObjectRef(newObject); else c.target = new ObjectRef(newObject, newObject.getSkeleton().getJoint(c.target.getJoint().id)); } } } /** Write a serialized representation of this track to a stream. */ public void writeToStream(DataOutputStream out, Scene scene) throws IOException { out.writeShort(1); // Version number out.writeUTF(name); out.writeBoolean(enabled); out.writeBoolean(useGestures); out.writeInt(constraints.size()); for (int i = 0; i < constraints.size(); i++) { Constraint c = (Constraint) constraints.elementAt(i); out.writeInt(c.jointID); out.writeBoolean(c.target != null); if (c.target != null) c.target.writeToStream(out); } theWeight.writeToStream(out, scene); } /** Initialize this tracked based on its serialized representation as written by writeToStream(). */ public void initFromStream(DataInputStream in, Scene scene) throws IOException, InvalidObjectException { short version = in.readShort(); if (version < 0 || version > 1) throw new InvalidObjectException(""); name = in.readUTF(); enabled = in.readBoolean(); if (version > 0) useGestures = in.readBoolean(); int numConstraints = in.readInt(); constraints = new Vector(); for (int i = 0; i < numConstraints; i++) { Constraint c = new Constraint(in.readInt(), in.readBoolean() ? new ObjectRef(in, scene) : null); constraints.addElement(c); } theWeight.initFromStream(in, scene); } /** This inner class represents a single constraint. */ private class Constraint { public int jointID; public ObjectRef target; public Constraint(int id, ObjectRef t) { jointID = id; target = t; } public Constraint duplicate() { if (target == null) return new Constraint(jointID, null); return new Constraint(jointID, target.duplicate()); } } /** Inner class for editing constraint tracks. */ private class Editor extends BDialog { LayoutWindow window; BList constraintList; BTextField nameField; BCheckBox gesturesBox; Vector tempConstraints; int tempJointID[]; ObjectRef tempTarget[]; BButton editButton, deleteButton; public Editor(LayoutWindow win) { super(win, Translate.text("ikTrackTitle"), true); window = win; tempConstraints = new Vector(); for (int i = 0; i < constraints.size(); i++) tempConstraints.addElement(((Constraint) constraints.elementAt(i)).duplicate()); // Layout the dialog. FormContainer content = new FormContainer(new double [] {0.0, 1.0}, new double [] {0.0, 1.0, 0.0, 0.0}); setContent(content); content.setDefaultLayout(new LayoutInfo(LayoutInfo.CENTER, LayoutInfo.BOTH, null, null)); content.add(Translate.label("trackName"), 0, 0); content.add(Translate.label("constraints"), 0, 1); content.add(nameField = new BTextField(IKTrack.this.getName(), 30), 1, 0); content.add(UIUtilities.createScrollingList(constraintList = new BList()), 1, 1); constraintList.setPreferredVisibleRows(5); constraintList.addEventLink(SelectionChangedEvent.class, this, "selectionChanged"); constraintList.addEventLink(MouseClickedEvent.class, this, "mouseClicked"); buildConstraintList(); content.add(gesturesBox = new BCheckBox(Translate.text("useGesturesToShapeMesh"), useGestures), 0, 2, 2, 1); gesturesBox.setEnabled(Actor.getActor(info.getObject()) != null); RowContainer buttons = new RowContainer(); content.add(buttons, 0, 3, 2, 1, new LayoutInfo()); buttons.add(Translate.button("add", "...", this, "doAdd")); buttons.add(editButton = Translate.button("edit", "...", this, "doEdit")); buttons.add(deleteButton = Translate.button("delete", this, "doDelete")); buttons.add(Translate.button("ok", this, "doOk")); buttons.add(Translate.button("cancel", this, "dispose")); pack(); UIUtilities.centerDialog(this, win); editButton.setEnabled(false); deleteButton.setEnabled(false); setVisible(true); } /** Fill in the list of constraints. */ private void buildConstraintList() { Skeleton skeleton = info.getSkeleton(); constraintList.removeAll(); if (tempConstraints.size() == 0) { constraintList.add("(No Constraints)"); constraintList.setEnabled(false); return; } constraintList.setEnabled(true); for (int i = 0; i < tempConstraints.size(); i++) { Constraint c = (Constraint) tempConstraints.elementAt(i); Joint j = skeleton.getJoint(c.jointID); if (c.target == null) constraintList.add(Translate.text("jointIsLocked", j.name)); else constraintList.add(Translate.text("jointFollowsTarget", j.name, c.target.toString())); } } private void doAdd() { Constraint c = new Constraint(-1, null); if (editConstraint(c)) { tempConstraints.addElement(c); buildConstraintList(); } } private void doEdit() { if (constraintList.getSelectedIndex() > -1) { Constraint c = (Constraint) tempConstraints.elementAt(constraintList.getSelectedIndex()); if (editConstraint(c)) buildConstraintList(); } } private void doDelete() { if (constraintList.getSelectedIndex() > -1) tempConstraints.removeElementAt(constraintList.getSelectedIndex()); buildConstraintList(); } private void doOk() { window.setUndoRecord(new UndoRecord(window, false, UndoRecord.COPY_OBJECT_INFO, new Object [] {info, info.duplicate()})); IKTrack.this.setName(nameField.getText()); IKTrack.this.setUseGestures(gesturesBox.getState()); constraints = tempConstraints; window.getScore().repaintAll(); dispose(); } private void mouseClicked(MouseClickedEvent ev) { if (ev.getClickCount() == 2) doEdit(); } /** Update the components when a selection changes. */ private void selectionChanged() { editButton.setEnabled(constraintList.getSelectedIndex() > -1); deleteButton.setEnabled(constraintList.getSelectedIndex() > -1); } /** Display a window for editing a single constraint. */ private boolean editConstraint(Constraint c) { Skeleton skeleton = info.getSkeleton(); Joint joint[] = skeleton.getJoints(); BList jointList = new BList(); for (int i = 0; i < joint.length; i++) jointList.add(joint[i].name); if (skeleton.findJointIndex(c.jointID) > -1) jointList.setSelected(skeleton.findJointIndex(c.jointID), true); jointList.setPreferredVisibleRows(8); RadioButtonGroup group = new RadioButtonGroup(); BRadioButton lockedBox = new BRadioButton(Translate.text("locked"), c.target == null, group); final BRadioButton targetBox = new BRadioButton(Translate.text("followsTarget"), c.target != null, group); RowContainer targetRow = new RowContainer(); targetRow.add(lockedBox); targetRow.add(targetBox); ObjectRef tempRef = (c.target == null ? new ObjectRef() : c.target); final ObjectRefSelector selector = new ObjectRefSelector(tempRef, window, Translate.text("targetForJoint"), info); Object listener = new Object() { private void processEvent(ValueChangedEvent ev) { selector.setEnabled(ev.getWidget() == targetBox); } }; lockedBox.addEventLink(ValueChangedEvent.class, listener); targetBox.addEventLink(ValueChangedEvent.class, listener); selector.setEnabled(c.target != null); ComponentsDialog dlg = new ComponentsDialog(window, Translate.text("editConstraint"), new Widget [] {UIUtilities.createScrollingList(jointList), targetRow, selector}, new String [] {Translate.text("applyConstraintTo"), Translate.text("constraintType"), Translate.text("targetForJoint")}); if (!dlg.clickedOk() || jointList.getSelectedIndex() == -1) return false; if (jointList.getSelectedIndex() > -1) c.jointID = joint[jointList.getSelectedIndex()].id; if (lockedBox.getState()) c.target = null; else c.target = selector.getSelection(); return true; } } }

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.22726.763−749.983
Source linesThe number of non-empty source lines.473+189.2
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.756−7.133

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

Score0.683

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.474−15.747
Indentation frequencyHow rapidly indentation changes from line to line.461+15.208
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.461−10.158
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.472.902+6.2
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.161.975−3.195
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.161.992+1.809
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.11−0.125

Intercept 0.07 + feature contributions = -5.937 (log-odds).
Score = sigmoid(-5.937) = 0.003.

Score0.737
Score261
Run 1

The code has a clear structure with good separation of concerns, and methods generally follow single-action-per-line principles. However, there are several readability issues: deep nesting in functions like apply() and editConstraint(), use of raw types (Vector, BList) that make intent ambiguous, and long parameter lists. Some methods have unclear return values (e.g., moveKeyframe returns -1 without explanation), and the inner class Editor is quite lengthy with mixed responsibilities. The naming is generally good but inconsistent (e.g., tempConstraints vs constraints). The reading flow is mostly natural, but the deeply nested conditionals and frequent type casts interrupt comprehension. Duplicate code in duplicate() and copy() could be refactored. Overall, functional but could benefit from flattening conditionals and using generics.

Run 2

The code demonstrates solid readability with clear structure, logical organization, and well-documented methods. It has a single class with reasonable length, flat nesting, and clear intent throughout. Each method performs a focused task with good naming conventions and JavaDoc comments explaining purposes. The Editor inner class appropriately handles UI concerns separately from data logic. Variable names are descriptive (constraints, theWeight, useGestures, etc.), and method names clearly indicate their actions. The code uses blank lines effectively to separate logical blocks and maintains consistent formatting. Minor deductions: some methods could be slightly more concise (apply() and editConstraint() have moderate complexity), and a few comments are redundant (e.g., 'Layout the dialog' before obviously layout code). Overall, the code is highly maintainable and readable.

Run 3

The code is generally well-structured with clear method separation and consistent naming conventions. The intent is mostly clear, particularly in public API methods like apply(), duplicate(), and writeToStream(), which read naturally. However, readability suffers in several areas: the inner Editor class is long and contains UI construction logic mixed with event handling, making it harder to follow. Methods like editConstraint() are dense with nested operations and multiple actions per line. There is some unnecessary verbosity with repetitive constraint iteration patterns using Vector and casting, which could be simplified with generics or helper methods. Nesting remains mostly flat, and comments are helpful, especially for public methods, but the constraint-handling logic is scattered across multiple methods, reducing cohesion. Action granularity is inconsistent—some methods are concise and single-purpose, while others perform both state changes and UI updates. The use of raw types and manual Vector casting adds cognitive overhead, and the serialization/deserialization logic, while functional, is not especially self-documenting. Overall, the code is readable enough for a developer familiar with the domain but could benefit from refactoring the inner class and reducing repetitive constraint iteration.

Run 1

Code Structure: Clearly separated methods and inner classes organize track behavior, serialization, constraints, and editing, though combining UI and domain logic makes the class large. Nesting: Mostly shallow, with early returns improving readability; constraint processing and event handling introduce moderate nesting. Clarity of intent: Descriptive method names and documentation explain most behavior, but abbreviated variables, raw Vectors with casts, and null representing a locked constraint require interpretation. Code length: Generally purposeful, although duplicated constraint-copying loops, verbose UI setup, and redundant checks add bulk. Action granularity: Most lines perform one action, but assignments embedded in widget-construction calls and long expressions combine operations. Reading flow: Consistent formatting and method grouping support natural reading; lengthy constructors, anonymous listeners, and string-based event bindings occasionally interrupt it.

Run 2

Code Structure: Methods are logically separated, with dedicated inner classes for constraints and editing, although animation logic, persistence, and UI share one large class. Nesting: Generally shallow, aided by early returns; constraint processing and event handling introduce moderate nesting. Clarity of intent: Descriptive method names and documentation explain most operations, but terse variables, raw Vectors, repeated casts, and implicit null-as-locked semantics require extra interpretation. Code length: Mostly justified by functionality, though duplicate/copy logic, repeated collection traversal, and lengthy UI construction could be consolidated. Action granularity: Most lines perform one action, but assignments embedded in widget creation and complex constructor expressions combine responsibilities. Reading flow: Consistent formatting and method grouping make the code easy to follow overall; long UI statements, anonymous event listeners, and string-based event links occasionally interrupt the flow.

Run 3

Code Structure: Methods are logically separated, with dedicated constraint and editor classes, though animation logic, persistence, and UI remain in one large class. Nesting: Generally shallow, aided by early returns; constraint processing and UI callbacks introduce moderate nesting. Clarity of intent: Descriptive method names and documentation explain most operations, but abbreviated variables, raw Vectors, repeated casts, and implicit null meanings reduce clarity. Code length: Mostly purposeful, although duplicated copying logic, repetitive collection traversal, and lengthy UI setup could be extracted or simplified. Action granularity: Most lines perform one action, but assignments embedded in UI construction calls combine initialization and registration. Reading flow: Consistent formatting and method grouping support natural reading; long constructor expressions, string-based event bindings, and occasional redundant checks interrupt it.