blender-3d 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|