OSDN Git Service

merge from jme10694
[mikumikustudio/MikuMikuStudio.git] / engine / src / ogre / com / jme3 / scene / plugins / ogre / SceneMaterialLoader.java
1 /*
2  * Copyright (c) 2009-2012 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package com.jme3.scene.plugins.ogre;
33
34 import com.jme3.asset.AssetManager;
35 import com.jme3.asset.AssetNotFoundException;
36 import com.jme3.material.MaterialList;
37 import com.jme3.scene.plugins.ogre.matext.OgreMaterialKey;
38 import java.io.File;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.io.InputStreamReader;
42 import java.util.Stack;
43 import java.util.logging.Level;
44 import java.util.logging.Logger;
45 import javax.xml.parsers.ParserConfigurationException;
46 import javax.xml.parsers.SAXParserFactory;
47 import org.xml.sax.Attributes;
48 import org.xml.sax.InputSource;
49 import org.xml.sax.SAXException;
50 import org.xml.sax.XMLReader;
51 import org.xml.sax.helpers.DefaultHandler;
52
53 /**
54  * This is a utility class to load a {@link MaterialList} from a 
55  * .scene file. It is only needed because the parsing method
56  * used by the SceneLoader doesn't support reading bottom XML nodes
57  * before reading the top nodes.
58  * 
59  * @author Kirill Vainer
60  */
61 class SceneMaterialLoader extends DefaultHandler {
62     
63     private static final Logger logger = Logger.getLogger(SceneMaterialLoader.class.getName());
64     private Stack<String> elementStack = new Stack<String>();
65     private String folderName;
66     private MaterialList materialList;
67     private AssetManager assetManager;
68     private boolean ignoreItem = false;
69     
70     private void reset(){
71         elementStack.clear();
72         materialList = null;
73         ignoreItem = false;
74     }
75     
76     private void checkTopNode(String topNode) throws SAXException{
77         if (!elementStack.peek().equals(topNode)){
78             throw new SAXException("dotScene parse error: Expected parent node to be " + topNode);
79         }
80     }
81     
82     @Override
83     public void startElement(String uri, String localName, String qName, Attributes attribs) throws SAXException {
84         if (qName.equals("externals")) {
85             checkTopNode("scene");
86             
87             // Has an externals block, create material list.
88             materialList = new MaterialList();
89         } else if (qName.equals("item")) {
90             checkTopNode("externals");
91             if (!attribs.getValue("type").equals("material")) {
92                 // This is not a material external. Ignore it.
93                 ignoreItem = true;
94             }
95         } else if (qName.equals("file")) {
96             checkTopNode("item");
97
98             if (!ignoreItem) {
99                 String materialPath = attribs.getValue("name");
100                 String materialName = new File(materialPath).getName();
101                 String matFile = folderName + materialName;
102                 try {
103                     MaterialList loadedMaterialList = (MaterialList) assetManager.loadAsset(new OgreMaterialKey(matFile));
104                     materialList.putAll(loadedMaterialList);
105                 } catch (AssetNotFoundException ex) {
106                     logger.log(Level.WARNING, "Cannot locate material file: {0}", matFile);
107                 }
108             }
109         }
110         elementStack.push(qName);
111     }
112     
113     @Override
114     public void endElement(String uri, String name, String qName) throws SAXException {
115         if (qName.equals("item") && ignoreItem) {
116             ignoreItem = false;
117         }
118         checkTopNode(qName);
119         elementStack.pop();
120     }
121     
122     public MaterialList load(AssetManager assetManager, String folderName, InputStream in) throws IOException {
123         try {
124             this.assetManager = assetManager;
125             this.folderName = folderName;
126             
127             reset();
128             
129             SAXParserFactory factory = SAXParserFactory.newInstance();
130             factory.setNamespaceAware(true);  
131             XMLReader xr = factory.newSAXParser().getXMLReader();  
132
133             xr.setContentHandler(this);
134             xr.setErrorHandler(this);
135
136             InputStreamReader r = null;
137
138             try {
139                 r = new InputStreamReader(in);
140                 xr.parse(new InputSource(r));
141             } finally {
142                 if (r != null){
143                     r.close();
144                 }
145             }
146             
147             return materialList;
148         } catch (SAXException ex) {
149             IOException ioEx = new IOException("Error while parsing Ogre3D dotScene");
150             ioEx.initCause(ex);
151             throw ioEx;
152         } catch (ParserConfigurationException ex) {
153             IOException ioEx = new IOException("Error while parsing Ogre3D dotScene");
154             ioEx.initCause(ex);
155             throw ioEx;
156         }
157     }
158 }