blender-3d 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/blender-3d.rb +31 -0
- data/lib/blender-3d/char_field_parser.rb +39 -0
- data/lib/blender-3d/dna_block.rb +74 -0
- data/lib/blender-3d/field.rb +17 -0
- data/lib/blender-3d/field_parser_factory.rb +10 -0
- data/lib/blender-3d/file_block.rb +44 -0
- data/lib/blender-3d/file_header.rb +41 -0
- data/lib/blender-3d/generic_field_parser.rb +54 -0
- data/lib/blender-3d/model.rb +56 -0
- data/lib/blender-3d/object_reader.rb +47 -0
- data/lib/blender-3d/pointer.rb +27 -0
- data/lib/blender-3d/structure.rb +19 -0
- data/lib/blender-3d/structure_definition.rb +27 -0
- data/lib/blender-3d/types.rb +140 -0
- data/lib/blender-3d/version.rb +3 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 14b1b6b25b75bc3144579623d6ebaf1eb20ed295
|
4
|
+
data.tar.gz: 94d505a329ebe729c2970ad9cf563829b365bcf4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b10f4977194b4c18d5790b7bcb2aaf2674404751bf0aa63843eaafbd6df47626ad5db875099e6a5f090f2e4e49a2b76258ed97ce84db43eb9fb5afa4ac1a491f
|
7
|
+
data.tar.gz: 4eea3fb816ffb01d0fcf08e1a77a7ba7cad124a813dcc953b837bb7b7c2e64feba455f62635053fc3c033b0c7aec11f97a7014bcd1cd728c3885481ec2610e00
|
data/lib/blender-3d.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
require_relative 'blender-3d/version'
|
4
|
+
require_relative 'blender-3d/object_reader'
|
5
|
+
|
6
|
+
require_relative 'blender-3d/pointer'
|
7
|
+
require_relative 'blender-3d/types'
|
8
|
+
require_relative 'blender-3d/field'
|
9
|
+
require_relative 'blender-3d/char_field_parser'
|
10
|
+
require_relative 'blender-3d/generic_field_parser'
|
11
|
+
require_relative 'blender-3d/field_parser_factory'
|
12
|
+
|
13
|
+
require_relative 'blender-3d/structure'
|
14
|
+
require_relative 'blender-3d/structure_definition'
|
15
|
+
|
16
|
+
require_relative 'blender-3d/file_header'
|
17
|
+
require_relative 'blender-3d/file_block'
|
18
|
+
require_relative 'blender-3d/dna_block'
|
19
|
+
require_relative 'blender-3d/model'
|
20
|
+
|
21
|
+
|
22
|
+
=begin
|
23
|
+
|
24
|
+
Usage:
|
25
|
+
|
26
|
+
require 'blender-3d'
|
27
|
+
# require_relative 'blender-3d'
|
28
|
+
|
29
|
+
model = Blender3d::Model.from_file('cube.blend');
|
30
|
+
|
31
|
+
=end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class CharFieldParser
|
3
|
+
def initialize(name)
|
4
|
+
@name = name
|
5
|
+
end
|
6
|
+
|
7
|
+
def parse
|
8
|
+
type = case @name
|
9
|
+
when GenericFieldParser::FUNCTION_POINTER
|
10
|
+
FunctionPointerType.new(SimpleType.new(FieldParserFactory::CHAR_TYPE))
|
11
|
+
|
12
|
+
when GenericFieldParser::POINTER_ARRAY
|
13
|
+
array_size = $2.to_i
|
14
|
+
ArrayType.new(NullTerminatedStringType.new, array_size)
|
15
|
+
|
16
|
+
when GenericFieldParser::MULTI_POINTER
|
17
|
+
PointerType.new(NullTerminatedStringType.new)
|
18
|
+
|
19
|
+
when GenericFieldParser::POINTER
|
20
|
+
NullTerminatedStringType.new
|
21
|
+
|
22
|
+
when GenericFieldParser::MULTI_ARRAY
|
23
|
+
array_size, string_size = $2.to_i, $3.to_i
|
24
|
+
ArrayType.new(FixedLengthStringType.new(string_size), array_size)
|
25
|
+
|
26
|
+
when GenericFieldParser::ARRAY
|
27
|
+
array_size = $2.to_i
|
28
|
+
FixedLengthStringType.new(array_size)
|
29
|
+
|
30
|
+
else
|
31
|
+
SimpleType.new(FieldParserFactory::CHAR_TYPE)
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
name = $1 || @name
|
36
|
+
Field.new(type, name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class DnaBlock
|
3
|
+
attr_accessor :code, :types, :structures
|
4
|
+
|
5
|
+
def initialize(reader = nil)
|
6
|
+
deserialize(reader) if reader
|
7
|
+
end
|
8
|
+
|
9
|
+
def deserialize(reader)
|
10
|
+
Reader.new(reader, self).read
|
11
|
+
end
|
12
|
+
|
13
|
+
class Reader
|
14
|
+
def initialize(reader, dna_block = DnaBlock.new)
|
15
|
+
@reader, @dna_block = reader, dna_block
|
16
|
+
end
|
17
|
+
|
18
|
+
def read
|
19
|
+
@dna_block.code = @reader.read(4)
|
20
|
+
@names = read_names
|
21
|
+
read_types
|
22
|
+
read_structures
|
23
|
+
@dna_block
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def read_names
|
29
|
+
@reader.read(4) # identifier 'NAME'
|
30
|
+
count = @reader.read_int32
|
31
|
+
count.times.map { @reader.read_string.chop.freeze }
|
32
|
+
end
|
33
|
+
|
34
|
+
def read_types
|
35
|
+
read_aligned # identifier 'TYPE' 4 byte aligned
|
36
|
+
|
37
|
+
count = @reader.read_int32
|
38
|
+
types = count.times.map { @reader.read_string.chop.freeze }
|
39
|
+
|
40
|
+
read_aligned # identifier 'TLEN' 4 byte aligned
|
41
|
+
lengths = count.times.map { @reader.read_int16 }
|
42
|
+
|
43
|
+
@dna_block.types = types.zip(lengths)
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_aligned
|
47
|
+
offset = 4 + (( 4 - (@reader.tell % 4) ) % 4)
|
48
|
+
@reader.read(offset)
|
49
|
+
end
|
50
|
+
|
51
|
+
def read_structures
|
52
|
+
read_aligned # identifier 'STRC' 4 byte aligned
|
53
|
+
count = @reader.read_int32
|
54
|
+
@dna_block.structures = count.times.map { read_structure }
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_structure
|
58
|
+
type_index = @reader.read_int16
|
59
|
+
num_fields = @reader.read_int16
|
60
|
+
|
61
|
+
fields = num_fields.times.map { read_field }
|
62
|
+
|
63
|
+
StructureDefinition.new(*@dna_block.types[type_index], fields)
|
64
|
+
end
|
65
|
+
|
66
|
+
def read_field
|
67
|
+
field_type = @dna_block.types[@reader.read_int16][0]
|
68
|
+
field_name = @names[@reader.read_int16]
|
69
|
+
factory = FieldParserFactory.create_for(field_type, field_name)
|
70
|
+
factory.parse
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class FileBlock
|
3
|
+
attr_accessor :code, :size, :pointer, :type_index, :count, :data, :type
|
4
|
+
|
5
|
+
def initialize(reader = nil)
|
6
|
+
deserialize(reader) if reader
|
7
|
+
end
|
8
|
+
|
9
|
+
def deserialize(reader)
|
10
|
+
Reader.new(reader, self).read
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse_data(model)
|
14
|
+
file = StringIO.new(self.data)
|
15
|
+
reader = model.create_reader(file)
|
16
|
+
self.data = self.count.times.map { self.type.read(reader) }
|
17
|
+
end
|
18
|
+
|
19
|
+
class Reader
|
20
|
+
def initialize(reader, file_block = FileBlock.new)
|
21
|
+
@reader, @file_block = reader, file_block
|
22
|
+
end
|
23
|
+
|
24
|
+
def read
|
25
|
+
@file_block.code = @reader.read(4).gsub(/\0.*$/, '')
|
26
|
+
@file_block.size = @reader.read_uint32
|
27
|
+
@file_block.pointer = Pointer.new(@reader.read_pointer)
|
28
|
+
@file_block.type_index = @reader.read_uint32
|
29
|
+
@file_block.count = @reader.read_uint32
|
30
|
+
@file_block.data = @reader.read(@file_block.size)
|
31
|
+
read_dna if @file_block.code == 'DNA1'
|
32
|
+
@file_block
|
33
|
+
end
|
34
|
+
|
35
|
+
private def read_dna
|
36
|
+
file = StringIO.new(@file_block.data)
|
37
|
+
@reader = @reader.model.create_reader(file)
|
38
|
+
@file_block.data = DnaBlock.new(@reader)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class FileHeader
|
3
|
+
attr_accessor :identifier,
|
4
|
+
:version
|
5
|
+
|
6
|
+
attr_reader :pointer_size, :size_code,
|
7
|
+
:endianness, :endian_code
|
8
|
+
|
9
|
+
def initialize(file = nil)
|
10
|
+
deserialize(file) if file
|
11
|
+
end
|
12
|
+
|
13
|
+
def deserialize(file)
|
14
|
+
self.identifier = file.read(7)
|
15
|
+
self.pointer_size = file.read(1) == '-'.freeze ? 8 : 4
|
16
|
+
self.endianness = file.read(1) == 'v'.freeze ? :little : :big
|
17
|
+
self.version = file.read(1) + '.'.freeze + file.read(2)
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def pointer_size=(value)
|
22
|
+
@pointer_size = value
|
23
|
+
@size_code = @pointer_size == 8 ? 'Q'.freeze : 'L'.freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
def endianness=(value)
|
27
|
+
@endianness = value
|
28
|
+
@endian_code = little_endian? ? '<'.freeze : '>'.freeze
|
29
|
+
end
|
30
|
+
|
31
|
+
def little_endian?
|
32
|
+
@endianness == :little
|
33
|
+
end
|
34
|
+
|
35
|
+
def big_endian?
|
36
|
+
!little_endian?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class GenericFieldParser
|
3
|
+
FUNCTION_POINTER = /^\(\*([^\)]+)\)\(\)$/
|
4
|
+
POINTER_ARRAY = /^\*([^\[]+)\[(\d+)\]$/
|
5
|
+
MULTI_POINTER = /^\*{2}(.+)$/
|
6
|
+
POINTER = /^\*(.+)$/
|
7
|
+
MULTI_ARRAY = /^([^\[]+)\[(\d+)\]\[(\d+)\]$/
|
8
|
+
ARRAY = /^([^\[]+)\[(\d+)\]$/
|
9
|
+
|
10
|
+
def initialize(type, name)
|
11
|
+
@type, @name = type, name
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse
|
15
|
+
type = case @name
|
16
|
+
when FUNCTION_POINTER
|
17
|
+
FunctionPointerType.new(@type)
|
18
|
+
|
19
|
+
when POINTER_ARRAY
|
20
|
+
array_size = $2.to_i
|
21
|
+
ArrayType.new(build_pointer_type, array_size)
|
22
|
+
|
23
|
+
when MULTI_POINTER
|
24
|
+
PointerType.new(build_pointer_type)
|
25
|
+
|
26
|
+
when POINTER
|
27
|
+
build_pointer_type
|
28
|
+
|
29
|
+
when MULTI_ARRAY
|
30
|
+
array1_size, array2_size = $2.to_i, $3.to_i
|
31
|
+
ArrayType.new(ArrayType.new(build_simple_type, array2_size), array1_size)
|
32
|
+
|
33
|
+
when ARRAY
|
34
|
+
array_size = $2.to_i
|
35
|
+
ArrayType.new(build_simple_type, array_size)
|
36
|
+
|
37
|
+
else
|
38
|
+
build_simple_type
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
name = $1 || @name
|
43
|
+
Field.new(type, name)
|
44
|
+
end
|
45
|
+
|
46
|
+
private def build_pointer_type
|
47
|
+
PointerType.new(build_simple_type)
|
48
|
+
end
|
49
|
+
|
50
|
+
private def build_simple_type
|
51
|
+
SimpleType.new(@type)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class Model
|
3
|
+
attr_reader :header, :blocks, :pointers
|
4
|
+
|
5
|
+
def self.from_file(path)
|
6
|
+
File.open(path, 'rb') { |file| new(file) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(file = nil)
|
10
|
+
@blocks = []
|
11
|
+
deserialize(file) if file
|
12
|
+
end
|
13
|
+
|
14
|
+
def deserialize(file)
|
15
|
+
@header = FileHeader.new(file)
|
16
|
+
reader = create_reader(file)
|
17
|
+
@blocks.clear
|
18
|
+
|
19
|
+
loop do
|
20
|
+
@blocks << FileBlock.new(reader)
|
21
|
+
break if reader.tell == reader.file.size
|
22
|
+
end
|
23
|
+
|
24
|
+
dna_block = self.dna_block
|
25
|
+
return self unless dna_block
|
26
|
+
|
27
|
+
@blocks.select { |block| block.type_index != 0 }.each do |block|
|
28
|
+
block.type = dna_block.data.structures[block.type_index]
|
29
|
+
block.parse_data(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
@pointers = {}
|
33
|
+
@blocks.each do |block|
|
34
|
+
if block.data.is_a?(Array)
|
35
|
+
pointer = block.pointer.location
|
36
|
+
block.data.each do |data|
|
37
|
+
@pointers[Pointer.new(pointer)] = data
|
38
|
+
pointer += data.class.definition.size
|
39
|
+
end
|
40
|
+
else
|
41
|
+
@pointers[block.pointer] = block.data
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def dna_block
|
49
|
+
@blocks.find { |block| block.code == 'DNA1' }
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_reader(file)
|
53
|
+
ObjectReader.new(file, self)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class ObjectReader
|
3
|
+
attr_reader :file
|
4
|
+
attr_accessor :model
|
5
|
+
|
6
|
+
def initialize(file, model = nil)
|
7
|
+
@file, @model = file, model
|
8
|
+
endian = @model.header.endian_code
|
9
|
+
|
10
|
+
%w'c s l q'.each.with_index do |code, i|
|
11
|
+
bytes = 1 << i
|
12
|
+
bits = 8 * bytes
|
13
|
+
name = 'int' + bits.to_s
|
14
|
+
define_reader name, bytes, code + endian
|
15
|
+
define_reader 'u' + name, bytes, code.upcase + endian
|
16
|
+
end
|
17
|
+
|
18
|
+
code = @model.header.little_endian? ? 'e' : 'g'
|
19
|
+
define_reader 'float', 4, code
|
20
|
+
define_reader 'double', 8, code.upcase
|
21
|
+
|
22
|
+
define_reader 'pointer', @model.header.pointer_size, @model.header.size_code + endian
|
23
|
+
end
|
24
|
+
|
25
|
+
private def define_reader(name, num_bytes, unpack_type)
|
26
|
+
instance_eval "def read_#{name}; @file.read(#{num_bytes}).unpack('#{unpack_type}').first end"
|
27
|
+
end
|
28
|
+
|
29
|
+
def read(length)
|
30
|
+
@file.read(length)
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_string
|
34
|
+
@file.gets("\0")
|
35
|
+
end
|
36
|
+
|
37
|
+
def seek(position)
|
38
|
+
@file.seek(position)
|
39
|
+
end
|
40
|
+
|
41
|
+
def tell
|
42
|
+
@file.tell
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class Pointer
|
3
|
+
attr_reader :location
|
4
|
+
|
5
|
+
def initialize(location)
|
6
|
+
@location = location
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
"Pointer(#{inspect})"
|
11
|
+
end
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
return '0x0' if @location == 0
|
15
|
+
return '0x%08x' % @location if @location < (1 << 32)
|
16
|
+
'0x%016x' % @location
|
17
|
+
end
|
18
|
+
|
19
|
+
def <=>(other)
|
20
|
+
other.is_a?(Pointer) ? location <=> other.location : 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
(self <=> other) == 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class Structure
|
3
|
+
class << self
|
4
|
+
attr_reader :definition
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(reader = nil)
|
8
|
+
deserialize(reader) if reader
|
9
|
+
end
|
10
|
+
|
11
|
+
def deserialize(reader)
|
12
|
+
self.class.definition.fields.each do |field|
|
13
|
+
value = field.type.read(reader)
|
14
|
+
instance_variable_set "@#{field.name}", value
|
15
|
+
end
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class StructureDefinition
|
3
|
+
attr_reader :name, :size, :fields
|
4
|
+
|
5
|
+
def initialize(name, size, fields = [])
|
6
|
+
name = name[0].upcase + name[1..-1]
|
7
|
+
@name, @size, @fields = name, size, fields
|
8
|
+
end
|
9
|
+
|
10
|
+
def read(reader)
|
11
|
+
structure_class.new(reader)
|
12
|
+
end
|
13
|
+
|
14
|
+
def structure_class
|
15
|
+
Blender3d.const_defined?(name, false) ? Blender3d.const_get(name, false) : define_structure_class
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def define_structure_class
|
21
|
+
fields = self.fields
|
22
|
+
struct_class = Class.new(Structure) { attr_accessor(*fields.map(&:name)) }
|
23
|
+
struct_class.instance_variable_set :@definition, self
|
24
|
+
Blender3d.const_set(name, struct_class)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Blender3d
|
2
|
+
class SimpleType
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@name = name
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
@name
|
11
|
+
end
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
@name
|
15
|
+
end
|
16
|
+
|
17
|
+
def read(reader)
|
18
|
+
case @name
|
19
|
+
when 'char' then reader.read(1)
|
20
|
+
when 'double' then reader.read_double
|
21
|
+
when 'float' then reader.read_float
|
22
|
+
when 'int' then reader.read_int32
|
23
|
+
when 'int64_t' then reader.read_int64
|
24
|
+
when 'long' then reader.read_int32
|
25
|
+
when 'short' then reader.read_int16
|
26
|
+
when 'uchar' then reader.read_uint8
|
27
|
+
when 'uint64_t' then reader.read_uint64
|
28
|
+
when 'ulong' then reader.read_uint32
|
29
|
+
when 'ushort' then reader.read_uint16
|
30
|
+
else
|
31
|
+
dna = reader.model.dna_block.data
|
32
|
+
struct = dna.structures.find { |struct| struct.name == @name }
|
33
|
+
return struct.read(reader) if struct
|
34
|
+
length = dna.types.find { |name, size| name == @name }&.last
|
35
|
+
return reader.read(length) if length
|
36
|
+
raise 'type not found'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class PointerType
|
42
|
+
attr_reader :type
|
43
|
+
|
44
|
+
def initialize(type)
|
45
|
+
@type = type
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
"Pointer(#@type)"
|
50
|
+
end
|
51
|
+
|
52
|
+
def inspect
|
53
|
+
"#{@type.inspect}*"
|
54
|
+
end
|
55
|
+
|
56
|
+
def read(reader)
|
57
|
+
Pointer.new(reader.read_pointer)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class FunctionPointerType
|
62
|
+
attr_reader :return_type
|
63
|
+
|
64
|
+
def initialize(return_type)
|
65
|
+
@return_type = return_type
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
"Function(#@return_type)"
|
70
|
+
end
|
71
|
+
|
72
|
+
def inspect
|
73
|
+
"#{@return_type.inspect} (*)()"
|
74
|
+
end
|
75
|
+
|
76
|
+
def read(reader)
|
77
|
+
Pointer.new(reader.read_pointer)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# equivalent to PointerType<SimpleType<char>> (char*)
|
82
|
+
class NullTerminatedStringType
|
83
|
+
def to_s
|
84
|
+
"NullTerminatedString"
|
85
|
+
end
|
86
|
+
|
87
|
+
def inspect
|
88
|
+
'char*'
|
89
|
+
end
|
90
|
+
|
91
|
+
def read(reader)
|
92
|
+
reader.read_string.chop
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# equivalent to ArrayType<SimpleType<char>, length> (char[length])
|
97
|
+
class FixedLengthStringType
|
98
|
+
attr_reader :length
|
99
|
+
|
100
|
+
def initialize(length)
|
101
|
+
@length = length
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
"FixedLengthString(#@length)"
|
106
|
+
end
|
107
|
+
|
108
|
+
def inspect
|
109
|
+
"char[#@length]"
|
110
|
+
end
|
111
|
+
|
112
|
+
def read(reader)
|
113
|
+
reader.read(@length).gsub(/\0.*$/, '')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class ArrayType
|
118
|
+
attr_reader :type, :size
|
119
|
+
|
120
|
+
def initialize(type, size)
|
121
|
+
@type, @size = type, size
|
122
|
+
end
|
123
|
+
|
124
|
+
def dimensions
|
125
|
+
@sizes.size
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_s
|
129
|
+
"Array[#@size](#@type)"
|
130
|
+
end
|
131
|
+
|
132
|
+
def inspect
|
133
|
+
"#{@type.inspect}[#@size]"
|
134
|
+
end
|
135
|
+
|
136
|
+
def read(reader)
|
137
|
+
@size.times.map { @type.read(reader) }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blender-3d
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- SilverPhoenix99
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-03 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Blender 3d file parser.
|
14
|
+
email:
|
15
|
+
- silver.phoenix99@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/blender-3d.rb
|
21
|
+
- lib/blender-3d/char_field_parser.rb
|
22
|
+
- lib/blender-3d/dna_block.rb
|
23
|
+
- lib/blender-3d/field.rb
|
24
|
+
- lib/blender-3d/field_parser_factory.rb
|
25
|
+
- lib/blender-3d/file_block.rb
|
26
|
+
- lib/blender-3d/file_header.rb
|
27
|
+
- lib/blender-3d/generic_field_parser.rb
|
28
|
+
- lib/blender-3d/model.rb
|
29
|
+
- lib/blender-3d/object_reader.rb
|
30
|
+
- lib/blender-3d/pointer.rb
|
31
|
+
- lib/blender-3d/structure.rb
|
32
|
+
- lib/blender-3d/structure_definition.rb
|
33
|
+
- lib/blender-3d/types.rb
|
34
|
+
- lib/blender-3d/version.rb
|
35
|
+
homepage:
|
36
|
+
licenses:
|
37
|
+
- MIT
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 2.6.6
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: Blender 3d file parser.
|
59
|
+
test_files: []
|