[COLLADA] Endless fighting with Swift and COLLADA blahhhhhh

This commit is contained in:
Eryn Wells 2015-10-31 12:52:12 -07:00
parent 9be3a41bdf
commit 662e95bcca
3 changed files with 234 additions and 0 deletions

View file

@ -10,6 +10,8 @@
C005E0221BE1CC3300F1BD3C /* COLLADA.h in Headers */ = {isa = PBXBuildFile; fileRef = C005E0211BE1CC3300F1BD3C /* COLLADA.h */; settings = {ATTRIBUTES = (Public, ); }; };
C005E0291BE1CC3300F1BD3C /* COLLADA.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C005E01E1BE1CC3300F1BD3C /* COLLADA.framework */; };
C005E02E1BE1CC3300F1BD3C /* COLLADATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C005E02D1BE1CC3300F1BD3C /* COLLADATests.swift */; };
C04449C31BE3422A00ABF046 /* COLLADA.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04449C21BE3422A00ABF046 /* COLLADA.swift */; };
C04449C51BE5142200ABF046 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04449C41BE5142200ABF046 /* Source.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -29,6 +31,8 @@
C005E0281BE1CC3300F1BD3C /* COLLADATests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = COLLADATests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C005E02D1BE1CC3300F1BD3C /* COLLADATests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = COLLADATests.swift; sourceTree = "<group>"; };
C005E02F1BE1CC3300F1BD3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C04449C21BE3422A00ABF046 /* COLLADA.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = COLLADA.swift; sourceTree = "<group>"; };
C04449C41BE5142200ABF046 /* Source.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Source.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -73,6 +77,8 @@
children = (
C005E0211BE1CC3300F1BD3C /* COLLADA.h */,
C005E0231BE1CC3300F1BD3C /* Info.plist */,
C04449C21BE3422A00ABF046 /* COLLADA.swift */,
C04449C41BE5142200ABF046 /* Source.swift */,
);
path = COLLADA;
sourceTree = "<group>";
@ -194,6 +200,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C04449C51BE5142200ABF046 /* Source.swift in Sources */,
C04449C31BE3422A00ABF046 /* COLLADA.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -305,6 +313,7 @@
C005E0331BE1CC3300F1BD3C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@ -317,12 +326,14 @@
PRODUCT_BUNDLE_IDENTIFIER = me.erynwells.graphics.COLLADA;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
C005E0341BE1CC3300F1BD3C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@ -379,6 +390,7 @@
C005E0341BE1CC3300F1BD3C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C005E0351BE1CC3300F1BD3C /* Build configuration list for PBXNativeTarget "COLLADATests" */ = {
isa = XCConfigurationList;
@ -387,6 +399,7 @@
C005E0371BE1CC3300F1BD3C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};

View file

@ -0,0 +1,129 @@
//
// COLLADA.swift
// COLLADA
//
// Created by Eryn Wells on 10/29/15.
// Copyright © 2015 Eryn Wells. All rights reserved.
//
import Foundation
private enum Node: String {
case Geometry = "geometry"
case LibraryGeometries = "library_geometries"
case Vertices = "vertices"
}
public class Scene: Object {
public enum Error: ErrorType {
case MissingRootElement
}
private let document: NSXMLDocument
public lazy var geometries: [Geometry] = {
do {
return try self.xml.elementsForName(Node.LibraryGeometries.rawValue).flatMap {
try $0.elementsForName(Node.Geometry.rawValue).map {
try Geometry(element: $0)
}
}
} catch {
return []
}
}()
init(document: NSXMLDocument) throws {
self.document = document
if let root = document.rootElement() {
try super.init(element: root)
} else {
try super.init(element: nil)
throw Error.MissingRootElement
}
}
}
public class Geometry: Object {
}
public class Mesh: Object {
private lazy var vertices: NSXMLElement! = {
return self.xml.elementsForName("vertices").first
}()
}
public class Polygons: Object {
}
public class Object {
public enum Error: ErrorType {
case MissingElement
case MultipleElementsWithSameID
}
// TODO: When the Swift compiler gets its shit together and lets you throw from init() without all stored properties being initialized, change these to `let` and clean up the initializer.
public private(set) var elements = [NSXMLElement]()
public private(set) var elementsByID = [String: NSXMLElement]()
let xml: NSXMLElement!
init(element: NSXMLElement!) throws {
xml = element
guard xml != nil else { throw Error.MissingElement }
for node in element.children ?? [] {
if node.kind != .ElementKind {
continue
}
if let element = node as? NSXMLElement {
elements.append(element)
}
}
for element in elements {
if let id = element.attributeForName("id")?.stringValue {
if elementsByID[id] != nil {
throw Error.MultipleElementsWithSameID
}
elementsByID[id] = element
}
}
}
public var id: String? {
return xml.attributeForName("id")?.stringValue
}
public var name: String? {
return xml.attributeForName("name")?.stringValue
}
private func idWithoutHash(id: String) -> String {
if id.hasPrefix("#") {
let indexAfterHash = id.startIndex.advancedBy(1)
return id.substringFromIndex(indexAfterHash)
} else {
return id
}
}
}
extension NSXMLElement {
func stringValueForAttributeWithName(name: String) -> String? {
if let value = self.attributeForName(name)?.stringValue {
return value
} else {
return nil
}
}
func unsignedIntValueForAttributeWithName(name: String) -> UInt? {
if let value = stringValueForAttributeWithName(name) {
return UInt(value)
} else {
return nil
}
}
}

View file

@ -0,0 +1,92 @@
//
// Source.swift
// COLLADA
//
// Created by Eryn Wells on 10/31/15.
// Copyright © 2015 Eryn Wells. All rights reserved.
//
import Foundation
import Math
private enum Node: String {
case Accessor = "accessor"
case FloatArray = "float_array"
case Source = "source"
case TechniqueCommon = "technique_common"
}
enum SourceError: ErrorType {
case MissingAccessor
}
protocol Source: SequenceType { }
class FloatSource: Object, Source {
// TODO: When the Swift compiler gets its shit together and lets you throw from init() without all stored properties being initialized, change these to `let` and clean up the initializer.
private var accessor: Accessor! = nil
override init(element: NSXMLElement!) throws {
try super.init(element: element)
if let techniqueNode = element.elementsForName(Node.TechniqueCommon.rawValue).first,
accessorNode = techniqueNode.elementsForName(Node.Accessor.rawValue).first {
accessor = try Accessor(element: accessorNode)
} else {
throw SourceError.MissingAccessor
}
}
}
extension FloatSource: SequenceType {
typealias Element = [String: Float]
typealias Generator = AnyGenerator<[String: Float]>
func generate() -> Generator {
return anyGenerator { () -> Element? in
return nil
}
}
}
class Vertices: Object {
}
class Accessor: Object {
typealias Param = (name: String, type: String)
enum Error: ErrorType {
case MissingSource
case MissingCount
case MissingStride
case MissingParamName
case MissingParamType
}
// TODO: When the Swift compiler gets its shit together and lets you throw from init() without all stored properties being initialized, change these to `let` and clean up the initializer.
private(set) var source: String! = nil
private(set) var count: UInt! = nil
private(set) var stride: UInt! = nil
private(set) var params: [Param]! = nil
override init(element: NSXMLElement!) throws {
try super.init(element: element)
source = element.stringValueForAttributeWithName("source")
guard source != nil else { throw Error.MissingSource }
count = element.unsignedIntValueForAttributeWithName("count")
guard count != nil else { throw Error.MissingCount }
stride = element.unsignedIntValueForAttributeWithName("stride")
guard stride != nil else { throw Error.MissingStride }
params = try element.elementsForName("param").map {
let name = $0.stringValueForAttributeWithName("name")
let type = $0.stringValueForAttributeWithName("type")
guard name != nil else { throw Error.MissingParamName }
guard type != nil else { throw Error.MissingParamType }
return (name: name!, type: type!)
}
}
}