Completed
Push — master ( c45d91...39b96d )
by Matthew
57s
created

ed2d.assets.OBJ.parse()   F

Complexity

Conditions 18

Size

Total Lines 69

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 18
dl 0
loc 69
rs 2.588

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like ed2d.assets.OBJ.parse() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
from ed2d.assets.mtlloader import MTL
2
from ed2d import files
3
4
class OBJ(object):
5
    def __init__(self, fileName):
6
        ''' Wavefront .obj file parser.'''
7
        objPath = files.resolve_path('data', 'models', fileName + '.obj')
8
9
        self.fmvnig = {}
10
        
11
        # Shared temporary storage of data
12
        self.tempVertices = []
13
        self.tempNormals = []
14
        self.tempUVs = []
15
16
        # Load the obj file
17
        with open(objPath, 'r') as objfile:
18
            self.lines = objfile.readlines()
19
        
20
        self.parse()
21
         
22
23
    def parse(self):
24
        ''' Perform the parsing of the obj format  '''
25
        
26
        matname = None
27
        lastType = None
28
        valueType = None
29
30
        for line in self.lines:
31
            lastType = valueType
32
            valueType, value = line.strip().split(' ', 1)
33
34
            # Don't bother unless the following key words exist in the line
35
            if valueType not in ['o', 'g', 'f', 'v', 'vt', 'vn', 'usemtl', 'mtllib']:
36
                continue
37
38
            value = value.split(' ')
39
40
            # Check first and continue on early because of string splitting
41
            if valueType == "usemtl":
42
                matname = value[0]
43
                continue
44
            
45
            if valueType in ['g', 'o']:
46
                # These objects reset state basically
47
                matname = None
48
                continue
49
            
50
            if valueType == 'mtllib':
51
                mtlpath = files.resolve_path('data', 'models', value[0])
52
                
53
                # Load the mtl file
54
                self.mtlfile = MTL(mtlpath)
55
                for material in self.mtlfile.data.keys():
56
                    self.fmvnig[material] = [ [], [], [] ]
57
                
58
                continue
59
60
            if valueType == "f":
61
                face = [item.split("/") for item in value]
62
                for typeGroup in face:
63
                    for typeIndex in range(len(typeGroup)):
64
                        if typeIndex == 0: # Vertex
65
                            typeSource = self.tempVertices
66
                        elif typeIndex == 1: # UV
67
                            typeSource = self.tempUVs
68
                        elif typeIndex == 2: # Normal
69
                            typeSource = self.tempNormals
70
                        
71
                        index = typeGroup[typeIndex]
72
                        
73
                        # Make sure data exists
74
                        if index != '':
75
                            index = int(index)
76
                            typeData = typeSource[index - 1]
77
                            
78
                            self.fmvnig[matname][typeIndex].append(typeData)
79
                continue
80
81
            # Map the values after the keyword to floats
82
            value = list(map(float, value))
83
84
            if valueType == "v":
85
                self.tempVertices.append(value)
86
87
            elif valueType == "vt":
88
                self.tempUVs.append(value * 2)
89
90
            elif valueType == "vn":
91
                self.tempNormals.append(value)
92