Added support for modifiers validating. Now modifiers that are invalid will not be loaded.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8245 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent ba57377795
commit 0775b93088
  1. 98
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java
  2. 146
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArrayModifier.java
  3. 21
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/MirrorModifier.java
  4. 12
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/Modifier.java
  5. 18
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ObjectAnimationModifier.java
  6. 27
      engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ParticlesModifier.java

@ -7,6 +7,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.animation.AnimControl; import com.jme3.animation.AnimControl;
import com.jme3.animation.Animation; import com.jme3.animation.Animation;
@ -43,6 +45,7 @@ import com.jme3.util.BufferUtils;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
/* package */class ArmatureModifier extends Modifier { /* package */class ArmatureModifier extends Modifier {
private static final Logger LOGGER = Logger.getLogger(ArmatureModifier.class.getName());
private static final int MAXIMUM_WEIGHTS_PER_VERTEX = 4; // have no idea why 4, could someone please explain ? private static final int MAXIMUM_WEIGHTS_PER_VERTEX = 4; // have no idea why 4, could someone please explain ?
/** Loaded animation data. */ /** Loaded animation data. */
@ -80,53 +83,55 @@ import com.jme3.util.BufferUtils;
* corrupted * corrupted
*/ */
public ArmatureModifier(Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException { public ArmatureModifier(Structure objectStructure, Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException {
Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); if(this.validate(modifierStructure, blenderContext)) {
if (pArmatureObject.isNotNull()) { Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object");
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); if (pArmatureObject.isNotNull()) {
ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class);
Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0);
this.armatureObjectOMA = armatureObject.getOldMemoryAddress(); Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0);
this.armatureObjectOMA = armatureObject.getOldMemoryAddress();
//read skeleton
// changing bones matrices so that they fit the current object //read skeleton
Structure armatureStructure = ((Pointer)armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); // changing bones matrices so that they fit the current object
Structure bonebase = (Structure) armatureStructure.getFieldValue("bonebase"); Structure armatureStructure = ((Pointer)armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0);
List<Structure> bonesStructures = bonebase.evaluateListBase(blenderContext); Structure bonebase = (Structure) armatureStructure.getFieldValue("bonebase");
for (Structure boneStructure : bonesStructures) { List<Structure> bonesStructures = bonebase.evaluateListBase(blenderContext);
BoneTransformationData rootBoneTransformationData = armatureHelper.readBoneAndItsChildren(boneStructure, null, blenderContext); for (Structure boneStructure : bonesStructures) {
armatureHelper.addBoneDataRoot(rootBoneTransformationData); BoneTransformationData rootBoneTransformationData = armatureHelper.readBoneAndItsChildren(boneStructure, null, blenderContext);
} armatureHelper.addBoneDataRoot(rootBoneTransformationData);
Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject); }
Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert(); Matrix4f armatureObjectMatrix = objectHelper.getTransformationMatrix(armatureObject);
Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix); Matrix4f inverseMeshObjectMatrix = objectHelper.getTransformationMatrix(objectStructure).invert();
Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation); Matrix4f additionalRootBoneTransformation = inverseMeshObjectMatrix.multLocal(armatureObjectMatrix);
Bone[] bones = armatureHelper.buildBonesStructure(Long.valueOf(0L), additionalRootBoneTransformation);
//read mesh indexes
Structure meshStructure = ((Pointer)objectStructure.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); //read mesh indexes
this.meshOMA = meshStructure.getOldMemoryAddress(); Structure meshStructure = ((Pointer)objectStructure.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0);
this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext); this.meshOMA = meshStructure.getOldMemoryAddress();
this.readVerticesWeightsData(objectStructure, meshStructure, blenderContext);
//read animations
String objectName = objectStructure.getName(); //read animations
Set<String> animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName); String objectName = objectStructure.getName();
if (animationNames != null && animationNames.size() > 0) { Set<String> animationNames = blenderContext.getBlenderKey().getAnimationNames(objectName);
ArrayList<Animation> animations = new ArrayList<Animation>(); if (animationNames != null && animationNames.size() > 0) {
List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); ArrayList<Animation> animations = new ArrayList<Animation>();
for (FileBlockHeader header : actionHeaders) { List<FileBlockHeader> actionHeaders = blenderContext.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00));
Structure actionStructure = header.getStructure(blenderContext); for (FileBlockHeader header : actionHeaders) {
String actionName = actionStructure.getName(); Structure actionStructure = header.getStructure(blenderContext);
if (animationNames.contains(actionName)) { String actionName = actionStructure.getName();
int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, actionName); if (animationNames.contains(actionName)) {
int fps = blenderContext.getBlenderKey().getFps(); int[] animationFrames = blenderContext.getBlenderKey().getAnimationFrames(objectName, actionName);
float start = (float) animationFrames[0] / (float) fps; int fps = blenderContext.getBlenderKey().getFps();
float stop = (float) animationFrames[1] / (float) fps; float start = (float) animationFrames[0] / (float) fps;
BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start); float stop = (float) animationFrames[1] / (float) fps;
boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, blenderContext, objectName, actionName)); BoneAnimation boneAnimation = new BoneAnimation(actionName, stop - start);
animations.add(boneAnimation); boneAnimation.setTracks(armatureHelper.getTracks(actionStructure, blenderContext, objectName, actionName));
animations.add(boneAnimation);
}
} }
animData = new AnimData(new Skeleton(bones), animations);
} }
animData = new AnimData(new Skeleton(bones), animations);
} }
} }
} }
@ -134,6 +139,9 @@ import com.jme3.util.BufferUtils;
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Node apply(Node node, BlenderContext blenderContext) { public Node apply(Node node, BlenderContext blenderContext) {
if(invalid) {
LOGGER.log(Level.WARNING, "Armature modifier is invalid! Cannot be applied to: {0}", node.getName());
}//if invalid, animData will be null
if(animData == null) { if(animData == null) {
return node; return node;
} }

@ -52,80 +52,86 @@ import com.jme3.scene.shape.Curve;
* corrupted * corrupted
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ArrayModifier(Structure modifier, BlenderContext blenderContext) throws BlenderFileException { public ArrayModifier(Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException {
Number fittype = (Number) modifier.getFieldValue("fit_type"); if(this.validate(modifierStructure, blenderContext)) {
modifierData.put("fittype", fittype); Number fittype = (Number) modifierStructure.getFieldValue("fit_type");
switch (fittype.intValue()) { modifierData.put("fittype", fittype);
case 0:// FIXED COUNT switch (fittype.intValue()) {
modifierData.put("count", modifier.getFieldValue("count")); case 0:// FIXED COUNT
break; modifierData.put("count", modifierStructure.getFieldValue("count"));
case 1:// FIXED LENGTH break;
modifierData.put("length", modifier.getFieldValue("length")); case 1:// FIXED LENGTH
break; modifierData.put("length", modifierStructure.getFieldValue("length"));
case 2:// FITCURVE break;
Pointer pCurveOb = (Pointer) modifier.getFieldValue("curve_ob"); case 2:// FITCURVE
float length = 0; Pointer pCurveOb = (Pointer) modifierStructure.getFieldValue("curve_ob");
if (pCurveOb.isNotNull()) { float length = 0;
Structure curveStructure = pCurveOb.fetchData(blenderContext.getInputStream()).get(0); if (pCurveOb.isNotNull()) {
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); Structure curveStructure = pCurveOb.fetchData(blenderContext.getInputStream()).get(0);
Node curveObject = (Node) objectHelper.toObject(curveStructure, blenderContext); ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
Set<Number> referencesToCurveLengths = new HashSet<Number>(curveObject.getChildren().size()); Node curveObject = (Node) objectHelper.toObject(curveStructure, blenderContext);
for (Spatial spatial : curveObject.getChildren()) { Set<Number> referencesToCurveLengths = new HashSet<Number>(curveObject.getChildren().size());
if (spatial instanceof Geometry) { for (Spatial spatial : curveObject.getChildren()) {
Mesh mesh = ((Geometry) spatial).getMesh(); if (spatial instanceof Geometry) {
if (mesh instanceof Curve) { Mesh mesh = ((Geometry) spatial).getMesh();
length += ((Curve) mesh).getLength(); if (mesh instanceof Curve) {
} else { length += ((Curve) mesh).getLength();
//if bevel object has several parts then each mesh will have the same reference } else {
//to length value (and we should use only one) //if bevel object has several parts then each mesh will have the same reference
Number curveLength = spatial.getUserData("curveLength"); //to length value (and we should use only one)
if (curveLength != null && !referencesToCurveLengths.contains(curveLength)) { Number curveLength = spatial.getUserData("curveLength");
length += curveLength.floatValue(); if (curveLength != null && !referencesToCurveLengths.contains(curveLength)) {
referencesToCurveLengths.add(curveLength); length += curveLength.floatValue();
} referencesToCurveLengths.add(curveLength);
} }
} }
} }
} }
modifierData.put("length", Float.valueOf(length)); }
modifierData.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH modifierData.put("length", Float.valueOf(length));
break; modifierData.put("fittype", Integer.valueOf(1));// treat it like FIXED LENGTH
default: break;
assert false : "Unknown array modifier fit type: " + fittype; default:
} assert false : "Unknown array modifier fit type: " + fittype;
}
// offset parameters
int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue(); // offset parameters
if ((offsettype & 0x01) != 0) {// Constant offset int offsettype = ((Number) modifierStructure.getFieldValue("offset_type")).intValue();
DynamicArray<Number> offsetArray = (DynamicArray<Number>) modifier.getFieldValue("offset"); if ((offsettype & 0x01) != 0) {// Constant offset
float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()}; DynamicArray<Number> offsetArray = (DynamicArray<Number>) modifierStructure.getFieldValue("offset");
modifierData.put("offset", offset); float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()};
} modifierData.put("offset", offset);
if ((offsettype & 0x02) != 0) {// Relative offset }
DynamicArray<Number> scaleArray = (DynamicArray<Number>) modifier.getFieldValue("scale"); if ((offsettype & 0x02) != 0) {// Relative offset
float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()}; DynamicArray<Number> scaleArray = (DynamicArray<Number>) modifierStructure.getFieldValue("scale");
modifierData.put("scale", scale); float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()};
} modifierData.put("scale", scale);
if ((offsettype & 0x04) != 0) {// Object offset }
Pointer pOffsetObject = (Pointer) modifier.getFieldValue("offset_ob"); if ((offsettype & 0x04) != 0) {// Object offset
if (pOffsetObject.isNotNull()) { Pointer pOffsetObject = (Pointer) modifierStructure.getFieldValue("offset_ob");
modifierData.put("offsetob", pOffsetObject); if (pOffsetObject.isNotNull()) {
} modifierData.put("offsetob", pOffsetObject);
} }
}
// start cap and end cap
Pointer pStartCap = (Pointer) modifier.getFieldValue("start_cap"); // start cap and end cap
if (pStartCap.isNotNull()) { Pointer pStartCap = (Pointer) modifierStructure.getFieldValue("start_cap");
modifierData.put("startcap", pStartCap); if (pStartCap.isNotNull()) {
} modifierData.put("startcap", pStartCap);
Pointer pEndCap = (Pointer) modifier.getFieldValue("end_cap"); }
if (pEndCap.isNotNull()) { Pointer pEndCap = (Pointer) modifierStructure.getFieldValue("end_cap");
modifierData.put("endcap", pEndCap); if (pEndCap.isNotNull()) {
} modifierData.put("endcap", pEndCap);
}
}
} }
@Override @Override
public Node apply(Node node, BlenderContext blenderContext) { public Node apply(Node node, BlenderContext blenderContext) {
if(invalid) {
LOGGER.log(Level.WARNING, "Array modifier is invalid! Cannot be applied to: {0}", node.getName());
return node;
}
int fittype = ((Number) modifierData.get("fittype")).intValue(); int fittype = ((Number) modifierData.get("fittype")).intValue();
float[] offset = (float[]) modifierData.get("offset"); float[] offset = (float[]) modifierData.get("offset");
if (offset == null) {// the node will be repeated several times in the same place if (offset == null) {// the node will be repeated several times in the same place

@ -48,17 +48,24 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
* this exception is thrown when the blender file is somehow * this exception is thrown when the blender file is somehow
* corrupted * corrupted
*/ */
public MirrorModifier(Structure modifier, BlenderContext blenderContext) { public MirrorModifier(Structure modifierStructure, BlenderContext blenderContext) {
modifierData.put("flag", modifier.getFieldValue("flag")); if(this.validate(modifierStructure, blenderContext)) {
modifierData.put("tolerance", modifier.getFieldValue("tolerance")); modifierData.put("flag", modifierStructure.getFieldValue("flag"));
Pointer pMirrorOb = (Pointer) modifier.getFieldValue("mirror_ob"); modifierData.put("tolerance", modifierStructure.getFieldValue("tolerance"));
if (pMirrorOb.isNotNull()) { Pointer pMirrorOb = (Pointer) modifierStructure.getFieldValue("mirror_ob");
modifierData.put("mirrorob", pMirrorOb); if (pMirrorOb.isNotNull()) {
} modifierData.put("mirrorob", pMirrorOb);
}
}
} }
@Override @Override
public Node apply(Node node, BlenderContext blenderContext) { public Node apply(Node node, BlenderContext blenderContext) {
if(invalid) {
LOGGER.log(Level.WARNING, "Mirror modifier is invalid! Cannot be applied to: {0}", node.getName());
return node;
}
int flag = ((Number) modifierData.get("flag")).intValue(); int flag = ((Number) modifierData.get("flag")).intValue();
float[] mirrorFactor = new float[]{ float[] mirrorFactor = new float[]{
(flag & 0x08) != 0 ? -1.0f : 1.0f, (flag & 0x08) != 0 ? -1.0f : 1.0f,

@ -2,6 +2,8 @@ package com.jme3.scene.plugins.blender.modifiers;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure;
/** /**
* This class represents an object's modifier. The modifier object can be varied * This class represents an object's modifier. The modifier object can be varied
@ -19,6 +21,9 @@ public abstract class Modifier {
public static final String MIRROR_MODIFIER_DATA = "MirrorModifierData"; public static final String MIRROR_MODIFIER_DATA = "MirrorModifierData";
public static final String OBJECT_ANIMATION_MODIFIER_DATA = "ObjectAnimationModifierData"; public static final String OBJECT_ANIMATION_MODIFIER_DATA = "ObjectAnimationModifierData";
/** This variable indicates if the modifier is invalid (<b>true</b>) or not (<b>false</b>). */
protected boolean invalid;
/** /**
* This method applies the modifier to the given node. * This method applies the modifier to the given node.
* *
@ -36,4 +41,11 @@ public abstract class Modifier {
* @return blender's type of modifier * @return blender's type of modifier
*/ */
public abstract String getType(); public abstract String getType();
protected boolean validate(Structure modifierStructure, BlenderContext blenderContext) {
Structure modifierData = (Structure)modifierStructure.getFieldValue("modifier");
Pointer pError = (Pointer) modifierData.getFieldValue("error");
invalid = pError.isNotNull();
return !invalid;
}
} }

@ -1,24 +1,11 @@
package com.jme3.scene.plugins.blender.modifiers; package com.jme3.scene.plugins.blender.modifiers;
import com.jme3.animation.Animation;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.jme3.animation.Bone;
import com.jme3.animation.BoneAnimation;
import com.jme3.animation.BoneTrack;
import com.jme3.animation.Skeleton;
import com.jme3.math.Transform;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.animations.Ipo;
import com.jme3.scene.plugins.blender.animations.IpoHelper;
import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
import com.jme3.scene.plugins.blender.file.FileBlockHeader;
import com.jme3.scene.plugins.blender.file.Pointer;
import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.objects.ObjectHelper;
import com.jme3.scene.plugins.ogre.AnimData; import com.jme3.scene.plugins.ogre.AnimData;
/** /**
@ -53,6 +40,8 @@ import com.jme3.scene.plugins.ogre.AnimData;
* corrupted * corrupted
*/ */
public ObjectAnimationModifier(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException { public ObjectAnimationModifier(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
LOGGER.warning("Object animation modifier not yet implemented!");
/*
Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo"); Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo");
if (pIpo.isNotNull()) { if (pIpo.isNotNull()) {
// check if there is an action name connected with this ipo // check if there is an action name connected with this ipo
@ -105,12 +94,13 @@ import com.jme3.scene.plugins.ogre.AnimData;
animData = new AnimData(new Skeleton(new Bone[] { bone }), animations); animData = new AnimData(new Skeleton(new Bone[] { bone }), animations);
objectOMA = objectStructure.getOldMemoryAddress(); objectOMA = objectStructure.getOldMemoryAddress();
} }
*/
} }
@Override @Override
public Node apply(Node node, BlenderContext blenderContext) { public Node apply(Node node, BlenderContext blenderContext) {
LOGGER.warning("Object animation modifier not yet implemented!"); LOGGER.warning("Object animation modifier not yet implemented!");
return null; return node;
} }
@Override @Override

@ -2,6 +2,8 @@ package com.jme3.scene.plugins.blender.modifiers;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.effect.ParticleEmitter; import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.shapes.EmitterMeshVertexShape; import com.jme3.effect.shapes.EmitterMeshVertexShape;
@ -24,13 +26,16 @@ import com.jme3.scene.plugins.blender.particles.ParticlesHelper;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
/* package */class ParticlesModifier extends Modifier { /* package */class ParticlesModifier extends Modifier {
private static final Logger LOGGER = Logger.getLogger(MirrorModifier.class.getName());
/** Loaded particles emitter. */
private ParticleEmitter particleEmitter; private ParticleEmitter particleEmitter;
/** /**
* This constructor reads the particles system structure and stores it in * This constructor reads the particles system structure and stores it in
* order to apply it later to the node. * order to apply it later to the node.
* *
* @param modifier * @param modifierStructure
* the structure of the modifier * the structure of the modifier
* @param blenderContext * @param blenderContext
* the blender context * the blender context
@ -38,18 +43,24 @@ import com.jme3.scene.plugins.blender.particles.ParticlesHelper;
* an exception is throw wneh there are problems with the * an exception is throw wneh there are problems with the
* blender file * blender file
*/ */
public ParticlesModifier(Structure modifier, BlenderContext blenderContext) public ParticlesModifier(Structure modifierStructure, BlenderContext blenderContext) throws BlenderFileException {
throws BlenderFileException { if(this.validate(modifierStructure, blenderContext)) {
Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys"); Pointer pParticleSystem = (Pointer) modifierStructure.getFieldValue("psys");
if (pParticleSystem.isNotNull()) { if (pParticleSystem.isNotNull()) {
ParticlesHelper particlesHelper = blenderContext.getHelper(ParticlesHelper.class); ParticlesHelper particlesHelper = blenderContext.getHelper(ParticlesHelper.class);
Structure particleSystem = pParticleSystem.fetchData(blenderContext.getInputStream()).get(0); Structure particleSystem = pParticleSystem.fetchData(blenderContext.getInputStream()).get(0);
particleEmitter = particlesHelper.toParticleEmitter(particleSystem, blenderContext); particleEmitter = particlesHelper.toParticleEmitter(particleSystem, blenderContext);
}
} }
} }
@Override @Override
public Node apply(Node node, BlenderContext blenderContext) { public Node apply(Node node, BlenderContext blenderContext) {
if(invalid) {
LOGGER.log(Level.WARNING, "Particles modifier is invalid! Cannot be applied to: {0}", node.getName());
return node;
}
MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class); MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
ParticleEmitter emitter = particleEmitter.clone(); ParticleEmitter emitter = particleEmitter.clone();

Loading…
Cancel
Save