package com.jme3.scene.plugins.blender.constraints; import java.util.logging.Level; import java.util.logging.Logger; import com.jme3.scene.Spatial; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType; import com.jme3.scene.plugins.blender.animations.BoneContext; import com.jme3.scene.plugins.blender.animations.Ipo; import com.jme3.scene.plugins.blender.file.BlenderFileException; import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.objects.ObjectHelper; /** * Constraint applied on the bone. * * @author Marcin Roguski (Kaelthas) */ /* package */class BoneConstraint extends Constraint { private static final Logger LOGGER = Logger.getLogger(BoneConstraint.class.getName()); /** * The bone constraint constructor. * * @param constraintStructure * the constraint's structure * @param ownerOMA * the OMA of the bone that owns the constraint * @param influenceIpo * the influence interpolation curve * @param blenderContext * the blender context * @throws BlenderFileException * exception thrown when problems with blender file occur */ public BoneConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException { super(constraintStructure, ownerOMA, influenceIpo, blenderContext); } @Override public boolean validate() { if (targetOMA != null) { Spatial nodeTarget = (Spatial) blenderContext.getLoadedFeature(targetOMA, LoadedDataType.FEATURE); if (nodeTarget == null) { LOGGER.log(Level.WARNING, "Cannot find target for constraint: {0}.", name); return false; } // the second part of the if expression verifies if the found node // (if any) is an armature node if (blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, nodeTarget) != null) { if (subtargetName.trim().isEmpty()) { LOGGER.log(Level.WARNING, "No bone target specified for constraint: {0}.", name); return false; } // if the target is not an object node then it is an Armature, // so make sure the bone is in the current skeleton BoneContext boneContext = blenderContext.getBoneContext(ownerOMA); if (targetOMA.longValue() != boneContext.getArmatureObjectOMA().longValue()) { LOGGER.log(Level.WARNING, "Bone constraint {0} must target bone in the its own skeleton! Targeting bone in another skeleton is not supported!", name); return false; } } } return constraintDefinition == null ? true : constraintDefinition.isTargetRequired(); } @Override public void apply(int frame) { super.apply(frame); blenderContext.getBoneContext(ownerOMA).getBone().updateModelTransforms(); } @Override public Long getTargetOMA() { if(targetOMA != null && subtargetName != null && !subtargetName.trim().isEmpty()) { Spatial nodeTarget = (Spatial) blenderContext.getLoadedFeature(targetOMA, LoadedDataType.FEATURE); if(nodeTarget != null) { if(blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, nodeTarget) != null) { BoneContext boneContext = blenderContext.getBoneByName(targetOMA, subtargetName); return boneContext != null ? boneContext.getBoneOma() : 0L; } return targetOMA; } } return 0L; } }