public void setUserData(String key, Object data) { if (userData == null) { userData = new HashMap<String, Savable>(); } if (data == null) { userData.remove(key); } else if (data instanceof Savable) { userData.put(key, (Savable) data); } else { userData.put(key, new UserData(UserData.getObjectType(data), data)); } }
public Collection<String> getUserDataKeys() { if (userData != null) { return userData.keySet(); } return Collections.EMPTY_SET; }
@SuppressWarnings("unchecked") public <T> T getUserData(String key) { if (userData == null) { return null; } Savable s = userData.get(key); if (s instanceof UserData) { return (T) ((UserData) s).getValue(); } else { return (T) s; } }
/** * @return A clone of this Spatial, the scene graph in its entirety is cloned and can be altered * independently of the original scene graph. * <p>Note that meshes of geometries are not cloned explicitly, they are shared if static, or * specially cloned if animated. * <p>All controls will be cloned using the Control.cloneForSpatial method on the clone. * @see Mesh#cloneForAnim() */ public Spatial clone(boolean cloneMaterial) { try { Spatial clone = (Spatial) super.clone(); if (worldBound != null) { clone.worldBound = worldBound.clone(); } clone.worldLights = worldLights.clone(); clone.localLights = localLights.clone(); // Set the new owner of the light lists clone.localLights.setOwner(clone); clone.worldLights.setOwner(clone); // No need to force cloned to update. // This node already has the refresh flags // set below so it will have to update anyway. clone.worldTransform = worldTransform.clone(); clone.localTransform = localTransform.clone(); if (clone instanceof Node) { Node node = (Node) this; Node nodeClone = (Node) clone; nodeClone.children = new SafeArrayList<Spatial>(Spatial.class); for (Spatial child : node.children) { Spatial childClone = child.clone(cloneMaterial); childClone.parent = nodeClone; nodeClone.children.add(childClone); } } clone.parent = null; clone.setBoundRefresh(); clone.setTransformRefresh(); clone.setLightListRefresh(); clone.controls = new SafeArrayList<Control>(Control.class); for (int i = 0; i < controls.size(); i++) { Control newControl = controls.get(i).cloneForSpatial(clone); newControl.setSpatial(clone); clone.controls.add(newControl); } if (userData != null) { clone.userData = (HashMap<String, Savable>) userData.clone(); } return clone; } catch (CloneNotSupportedException ex) { throw new AssertionError(); } }
/** * Select the technique to use for rendering this material. * * <p>If <code>name</code> is "Default", then one of the {@link MaterialDef#getDefaultTechniques() * default techniques} on the material will be selected. Otherwise, the named technique will be * found in the material definition. * * <p>Any candidate technique for selection (either default or named) must be verified to be * compatible with the system, for that, the <code>renderManager</code> is queried for * capabilities. * * @param name The name of the technique to select, pass "Default" to select one of the default * techniques. * @param renderManager The {@link RenderManager render manager} to query for capabilities. * @throws IllegalArgumentException If "Default" is passed and no default techniques are available * on the material definition, or if a name is passed but there's no technique by that name. * @throws UnsupportedOperationException If no candidate technique supports the system * capabilities. */ public void selectTechnique(String name, RenderManager renderManager) { // check if already created Technique tech = techniques.get(name); // When choosing technique, we choose one that // supports all the caps. EnumSet<Caps> rendererCaps = renderManager.getRenderer().getCaps(); if (tech == null) { if (name.equals("Default")) { List<TechniqueDef> techDefs = def.getDefaultTechniques(); if (techDefs == null || techDefs.isEmpty()) { throw new IllegalArgumentException( "No default techniques are available on material '" + def.getName() + "'"); } TechniqueDef lastTech = null; for (TechniqueDef techDef : techDefs) { if (rendererCaps.containsAll(techDef.getRequiredCaps())) { // use the first one that supports all the caps tech = new Technique(this, techDef); techniques.put(name, tech); break; } lastTech = techDef; } if (tech == null) { throw new UnsupportedOperationException( "No default technique on material '" + def.getName() + "'\n" + " is supported by the video hardware. The caps " + lastTech.getRequiredCaps() + " are required."); } } else { // create "special" technique instance TechniqueDef techDef = def.getTechniqueDef(name); if (techDef == null) { throw new IllegalArgumentException( "For material " + def.getName() + ", technique not found: " + name); } if (!rendererCaps.containsAll(techDef.getRequiredCaps())) { throw new UnsupportedOperationException( "The explicitly chosen technique '" + name + "' on material '" + def.getName() + "'\n" + "requires caps " + techDef.getRequiredCaps() + " which are not " + "supported by the video renderer"); } tech = new Technique(this, techDef); techniques.put(name, tech); } } else if (technique == tech) { // attempting to switch to an already // active technique. return; } technique = tech; tech.makeCurrent(def.getAssetManager(), true, rendererCaps); // shader was changed sortingId = -1; }
public void read(JmeImporter im) throws IOException { InputCapsule ic = im.getCapsule(this); additionalState = (RenderState) ic.readSavable("render_state", null); transparent = ic.readBoolean("is_transparent", false); // Load the material def String defName = ic.readString("material_def", null); HashMap<String, MatParam> params = (HashMap<String, MatParam>) ic.readStringSavableMap("parameters", null); boolean enableVcolor = false; boolean separateTexCoord = false; boolean applyDefaultValues = false; boolean guessRenderStateApply = false; int ver = ic.getSavableVersion(Material.class); if (ver < 1) { applyDefaultValues = true; } if (ver < 2) { guessRenderStateApply = true; } if (im.getFormatVersion() == 0) { // Enable compatibility with old models if (defName.equalsIgnoreCase("Common/MatDefs/Misc/VertexColor.j3md")) { // Using VertexColor, switch to Unshaded and set VertexColor=true enableVcolor = true; defName = "Common/MatDefs/Misc/Unshaded.j3md"; } else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/SimpleTextured.j3md") || defName.equalsIgnoreCase("Common/MatDefs/Misc/SolidColor.j3md")) { // Using SimpleTextured/SolidColor, just switch to Unshaded defName = "Common/MatDefs/Misc/Unshaded.j3md"; } else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/WireColor.j3md")) { // Using WireColor, set wireframe renderstate = true and use Unshaded getAdditionalRenderState().setWireframe(true); defName = "Common/MatDefs/Misc/Unshaded.j3md"; } else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/Unshaded.j3md")) { // Uses unshaded, ensure that the proper param is set MatParam value = params.get("SeperateTexCoord"); if (value != null && ((Boolean) value.getValue()) == true) { params.remove("SeperateTexCoord"); separateTexCoord = true; } } assert applyDefaultValues && guessRenderStateApply; } def = (MaterialDef) im.getAssetManager().loadAsset(new AssetKey(defName)); paramValues = new ListMap<String, MatParam>(); // load the textures and update nextTexUnit for (Map.Entry<String, MatParam> entry : params.entrySet()) { MatParam param = entry.getValue(); if (param instanceof MatParamTexture) { MatParamTexture texVal = (MatParamTexture) param; if (nextTexUnit < texVal.getUnit() + 1) { nextTexUnit = texVal.getUnit() + 1; } // the texture failed to load for this param // do not add to param values if (texVal.getTextureValue() == null || texVal.getTextureValue().getImage() == null) { continue; } } if (im.getFormatVersion() == 0 && param.getName().startsWith("m_")) { // Ancient version of jME3 ... param.setName(param.getName().substring(2)); } checkSetParam(param.getVarType(), param.getName()); paramValues.put(param.getName(), param); } if (applyDefaultValues) { // compatability with old versions where default vars were // not available for (MatParam param : def.getMaterialParams()) { if (param.getValue() != null && paramValues.get(param.getName()) == null) { setParam(param.getName(), param.getVarType(), param.getValue()); } } } if (guessRenderStateApply && additionalState != null) { // Try to guess values of "apply" render state based on defaults // if value != default then set apply to true additionalState.applyPolyOffset = additionalState.offsetEnabled; additionalState.applyAlphaFallOff = additionalState.alphaTest; additionalState.applyAlphaTest = additionalState.alphaTest; additionalState.applyBlendMode = additionalState.blendMode != BlendMode.Off; additionalState.applyColorWrite = !additionalState.colorWrite; additionalState.applyCullMode = additionalState.cullMode != FaceCullMode.Back; additionalState.applyDepthTest = !additionalState.depthTest; additionalState.applyDepthWrite = !additionalState.depthWrite; additionalState.applyPointSprite = additionalState.pointSprite; additionalState.applyStencilTest = additionalState.stencilTest; additionalState.applyWireFrame = additionalState.wireframe; } if (enableVcolor) { setBoolean("VertexColor", true); } if (separateTexCoord) { setBoolean("SeparateTexCoord", true); } }