diff --git a/GLLara.xcodeproj/project.pbxproj b/GLLara.xcodeproj/project.pbxproj index c50fddb5..9612678a 100644 --- a/GLLara.xcodeproj/project.pbxproj +++ b/GLLara.xcodeproj/project.pbxproj @@ -17,8 +17,8 @@ 5211F83226246EE600A1EC23 /* GLLTextureAssignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5211F83126246EE600A1EC23 /* GLLTextureAssignment.swift */; }; 5213F8831C0E411C007A9EBB /* GLLPreferencesWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5213F8811C0E411C007A9EBB /* GLLPreferencesWindowController.m */; }; 5213F8881C0E478C007A9EBB /* GLLPreferencesWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5213F88A1C0E478C007A9EBB /* GLLPreferencesWindow.xib */; }; - 5214470A16DBF206003E260F /* GLLItemMesh+MeshExport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5214470916DBF206003E260F /* GLLItemMesh+MeshExport.m */; }; - 5214470D16DC2312003E260F /* GLLItem+MeshExport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5214470C16DC2312003E260F /* GLLItem+MeshExport.m */; }; + 5214470A16DBF206003E260F /* GLLItemMesh+MeshExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5214470916DBF206003E260F /* GLLItemMesh+MeshExport.swift */; }; + 5214470D16DC2312003E260F /* GLLItem+MeshExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5214470C16DC2312003E260F /* GLLItem+MeshExport.swift */; }; 5214471116DE22E1003E260F /* GLLara.help in Resources */ = {isa = PBXBuildFile; fileRef = 5214471016DE22E0003E260F /* GLLara.help */; }; 52152CEF16B66951001AE54C /* GLLDDSFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 52152CEE16B66951001AE54C /* GLLDDSFile.m */; }; 52232EAE1EFC57D4007FE9AD /* XYAlignedSquare.obj in Resources */ = {isa = PBXBuildFile; fileRef = 52232EAD1EFC57D4007FE9AD /* XYAlignedSquare.obj */; }; @@ -404,10 +404,8 @@ 521446FC16DAD8C3003E260F /* de */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/RenderParameters.strings; sourceTree = ""; }; 521446FD16DAD8C3003E260F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = de; path = de.lproj/Credits.rtf; sourceTree = ""; }; 521446FE16DAD8C4003E260F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; - 5214470816DBF205003E260F /* GLLItemMesh+MeshExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GLLItemMesh+MeshExport.h"; sourceTree = ""; }; - 5214470916DBF206003E260F /* GLLItemMesh+MeshExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GLLItemMesh+MeshExport.m"; sourceTree = ""; }; - 5214470B16DC2312003E260F /* GLLItem+MeshExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GLLItem+MeshExport.h"; sourceTree = ""; }; - 5214470C16DC2312003E260F /* GLLItem+MeshExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GLLItem+MeshExport.m"; sourceTree = ""; }; + 5214470916DBF206003E260F /* GLLItemMesh+MeshExport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GLLItemMesh+MeshExport.swift"; sourceTree = ""; }; + 5214470C16DC2312003E260F /* GLLItem+MeshExport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GLLItem+MeshExport.swift"; sourceTree = ""; }; 5214471016DE22E0003E260F /* GLLara.help */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GLLara.help; sourceTree = ""; }; 52152CED16B66951001AE54C /* GLLDDSFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLLDDSFile.h; sourceTree = ""; }; 52152CEE16B66951001AE54C /* GLLDDSFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLLDDSFile.m; sourceTree = ""; }; @@ -1393,10 +1391,8 @@ 526AB31B1609C7C300940A74 /* GLLItem+OBJExport.m */, 523D368316BED849004FAD4B /* GLLItemMeshTexture.h */, 523D368416BED84A004FAD4B /* GLLItemMeshTexture.m */, - 5214470816DBF205003E260F /* GLLItemMesh+MeshExport.h */, - 5214470916DBF206003E260F /* GLLItemMesh+MeshExport.m */, - 5214470B16DC2312003E260F /* GLLItem+MeshExport.h */, - 5214470C16DC2312003E260F /* GLLItem+MeshExport.m */, + 5214470916DBF206003E260F /* GLLItemMesh+MeshExport.swift */, + 5214470C16DC2312003E260F /* GLLItem+MeshExport.swift */, 521102EE2899C430001BE4BC /* GLLItemBoneExtensions.swift */, ); name = "Scene members"; @@ -2000,8 +1996,8 @@ 5213F8831C0E411C007A9EBB /* GLLPreferencesWindowController.m in Sources */, 522783AD1C0B79F2002E43FD /* GLLItemMeshTextureSelectionPlaceholder.m in Sources */, 526756AA16BF543800FB85CA /* GLLImageView.m in Sources */, - 5214470A16DBF206003E260F /* GLLItemMesh+MeshExport.m in Sources */, - 5214470D16DC2312003E260F /* GLLItem+MeshExport.m in Sources */, + 5214470A16DBF206003E260F /* GLLItemMesh+MeshExport.swift in Sources */, + 5214470D16DC2312003E260F /* GLLItem+MeshExport.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2422,7 +2418,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 13.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = ""; SWIFT_VERSION = 5.0; @@ -2476,7 +2472,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 13.0; SDKROOT = ""; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_VERSION = 5.0; @@ -2501,7 +2497,7 @@ DEAD_CODE_STRIPPING = YES; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "GLLara/GLLara-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 0.3.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; PRODUCT_BUNDLE_IDENTIFIER = "${ORGANIZATION_IDENTIFIER}.${PRODUCT_NAME:rfc1034identifier}"; @@ -2526,7 +2522,7 @@ DEAD_CODE_STRIPPING = YES; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "GLLara/GLLara-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 0.3.0; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "${ORGANIZATION_IDENTIFIER}.${PRODUCT_NAME:rfc1034identifier}"; diff --git a/GLLara/GLLDocument.m b/GLLara/GLLDocument.m index 2e590144..0cdf599d 100644 --- a/GLLara/GLLDocument.m +++ b/GLLara/GLLDocument.m @@ -16,7 +16,6 @@ #import "GLLDirectionalLight.h" #import "GLLDocumentWindowController.h" #import "GLLItem.h" -#import "GLLItem+MeshExport.h" #import "GLLItemBone.h" #import "GLLItemMesh.h" #import "GLLItemMeshTexture.h" @@ -405,7 +404,7 @@ - (IBAction)exportItem:(id)sender; } // Save mesh file there - both with and without ascii - NSString *ascii = [item writeASCIIError:&error]; + NSString *ascii = [item writeASCIIAndReturnError:&error]; if (!ascii) { [manager removeItemAtURL:panel.URL error:NULL]; @@ -420,7 +419,7 @@ - (IBAction)exportItem:(id)sender; } // Ignore if writing binary fails; the mesh.ascii version includes all data already. - NSData *binary = [item writeBinaryError:NULL]; + NSData *binary = [item writeBinaryAndReturnError:NULL]; if (!binary) return; if (![binary writeToURL:[panel.URL URLByAppendingPathComponent:@"generic_item.mesh"] options:NSDataWritingAtomic error:&error]) return; }]; diff --git a/GLLara/GLLItem+MeshExport.h b/GLLara/GLLItem+MeshExport.h deleted file mode 100644 index 64634041..00000000 --- a/GLLara/GLLItem+MeshExport.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// GLLItem+MeshExport.h -// GLLara -// -// Created by Torsten Kammer on 25.02.13. -// Copyright (c) 2013 Torsten Kammer. All rights reserved. -// - -#import "GLLItem.h" - -@interface GLLItem (MeshExport) - -- (NSData *)writeBinaryError:(NSError *__autoreleasing*)error; -- (NSString *)writeASCIIError:(NSError *__autoreleasing*)error; - -@end diff --git a/GLLara/GLLItem+MeshExport.m b/GLLara/GLLItem+MeshExport.m deleted file mode 100644 index 23ee797d..00000000 --- a/GLLara/GLLItem+MeshExport.m +++ /dev/null @@ -1,58 +0,0 @@ -// -// GLLItem+MeshExport.m -// GLLara -// -// Created by Torsten Kammer on 25.02.13. -// Copyright (c) 2013 Torsten Kammer. All rights reserved. -// - -#import "GLLItem+MeshExport.h" - -#import "GLLItemBone.h" -#import "GLLItemMesh+MeshExport.h" -#import "TROutDataStream.h" - -#import "GLLara-Swift.h" - -@implementation GLLItem (MeshExport) - -- (NSData *)writeBinaryError:(NSError *__autoreleasing*)error; -{ - TROutDataStream *stream = [[TROutDataStream alloc] init]; - - [stream appendUint32:(uint32_t) self.bones.count]; - for (GLLItemBone *bone in self.bones) - [stream appendData:[bone.bone writeBinary]]; - - NSArray *toExport = [self.meshes.array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"shouldExport == YES"]]; - [stream appendUint32:(uint32_t) toExport.count]; - for (GLLItemMesh *mesh in toExport) - { - NSData *meshData = [mesh writeBinaryError:error]; - if (!meshData) return nil; - [stream appendData:meshData]; - } - - return stream.data; -} -- (NSString *)writeASCIIError:(NSError *__autoreleasing*)error; -{ - NSMutableString *string = [NSMutableString string]; - - [string appendFormat:@"%lu\n", self.bones.count]; - for (GLLItemBone *bone in self.bones) - [string appendFormat:@"%@\n", [bone.bone writeASCII]]; - - NSArray *toExport = [self.meshes.array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"shouldExport == YES"]]; - [string appendFormat:@"%lu\n", toExport.count]; - for (GLLItemMesh *mesh in toExport) - { - NSString *meshString = [mesh writeASCIIError:error]; - if (!meshString) return nil; - [string appendFormat:@"%@\n", meshString]; - } - - return string; -} - -@end diff --git a/GLLara/GLLItem+MeshExport.swift b/GLLara/GLLItem+MeshExport.swift new file mode 100644 index 00000000..7ad32239 --- /dev/null +++ b/GLLara/GLLItem+MeshExport.swift @@ -0,0 +1,65 @@ +// +// GLLItem+MeshExport.swift +// GLLara +// +// Created by Torsten Kammer on 25.02.13. +// Copyright (c) 2013 Torsten Kammer. All rights reserved. +// + +import Foundation + +extension GLLItem { + + @objc func writeBinary() throws -> Data { + let stream = TROutDataStream() + + stream.appendUint32(UInt32(bones.count)) + for bone in bones { + stream.appendData((bone as! GLLItemBone).bone.writeBinary()) + } + + var count: UInt32 = 0 + for mesh in meshes { + if (mesh as! GLLItemMesh).shouldExport { + count += 1 + } + } + stream.appendUint32(count) + for mesh in meshes { + let itemMesh = mesh as! GLLItemMesh + if itemMesh.shouldExport { + try stream.appendData(itemMesh.writeBinary()) + } + } + + return stream.data()!; + } + + @objc func writeASCII() throws -> String { + var string = "" + + string += "\(bones.count)\n" + for bone in bones { + string += (bone as! GLLItemBone).bone.writeASCII() + string += "\n" + } + + var count = 0 + for mesh in meshes { + if (mesh as! GLLItemMesh).shouldExport { + count += 1 + } + } + string += "\(count)\n" + for mesh in meshes { + let itemMesh = mesh as! GLLItemMesh + if itemMesh.shouldExport { + string += try itemMesh.writeASCII() + string += "\n" + } + } + + return string; + } + +} diff --git a/GLLara/GLLItemMesh+MeshExport.h b/GLLara/GLLItemMesh+MeshExport.h deleted file mode 100644 index 322140f0..00000000 --- a/GLLara/GLLItemMesh+MeshExport.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// GLLItemMesh+MeshExport.h -// GLLara -// -// Created by Torsten Kammer on 25.02.13. -// Copyright (c) 2013 Torsten Kammer. All rights reserved. -// - -#import "GLLItemMesh.h" - -@class XnaLaraShaderDescription; - -@interface GLLItemMesh (MeshExport) - -- (XnaLaraShaderDescription *)shaderDescriptionError:(NSError *__autoreleasing*)error; -- (NSString *)genericItemNameForShaderDescription:(XnaLaraShaderDescription *)xnaLaraShaderDescription; -- (NSArray *)textureUrlsForDescription:(XnaLaraShaderDescription *)xnaLaraShaderDescription; - -- (NSString *)writeASCIIError:(NSError *__autoreleasing*)error; -- (NSData *)writeBinaryError:(NSError *__autoreleasing*)error; - -@property (nonatomic, readonly) BOOL shouldExport; - -@end diff --git a/GLLara/GLLItemMesh+MeshExport.m b/GLLara/GLLItemMesh+MeshExport.m deleted file mode 100644 index 0282b0ff..00000000 --- a/GLLara/GLLItemMesh+MeshExport.m +++ /dev/null @@ -1,99 +0,0 @@ -// -// GLLItemMesh+MeshExport.m -// GLLara -// -// Created by Torsten Kammer on 25.02.13. -// Copyright (c) 2013 Torsten Kammer. All rights reserved. -// - -#import "GLLItemMesh+MeshExport.h" - -#import "GLLItemMeshTexture.h" -#import "GLLFloatRenderParameter.h" -#import "NSArray+Map.h" - -#import "GLLara-Swift.h" - -@implementation GLLItemMesh (MeshExport) - -- (XnaLaraShaderDescription *)shaderDescriptionError:(NSError *__autoreleasing*)error { - XnaLaraShaderDescription *description = [[self.mesh.model.parameters xnaLaraShaderDescriptions] firstObjectMatching:^BOOL(XnaLaraShaderDescription *description) { - - if (![description.baseName isEqual:self.shaderBase]) { - return NO; - } - NSSet* modules = [[NSSet alloc] initWithArray:description.moduleNames]; - if (![modules isEqual:self.shaderModules]) { - return NO; - } - return YES; - }]; - if (!description && error) { - *error = [NSError errorWithDomain:@"GLLMeshExporting" code:1 userInfo:@{ - NSLocalizedDescriptionKey : NSLocalizedString(@"Could not export model.", @"no mesh group found for model to export"), - NSLocalizedRecoverySuggestionErrorKey : [NSString stringWithFormat:NSLocalizedString(@"No XNALara Mesh Group number corresponds to the shader %@.", @"can't write meshes without tangents"), @""]}]; - } - return description; -} - -- (NSString *)genericItemNameForShaderDescription:(XnaLaraShaderDescription *)xnaLaraShaderDescription -{ - NSMutableString *genericItemName = [NSMutableString string]; - - // 1 - get mesh group - NSArray *possibleGroups = self.mesh.usesAlphaBlending ? xnaLaraShaderDescription.alphaMeshGroups : xnaLaraShaderDescription.solidMeshGroups; - NSRegularExpression *meshGroupNameRegexp = [NSRegularExpression regularExpressionWithPattern:@"^MeshGroup([0-9]+)$" options:0 error:NULL]; - for (NSString *groupName in possibleGroups) - { - NSTextCheckingResult *match = [meshGroupNameRegexp firstMatchInString:groupName options:NSMatchingAnchored range:NSMakeRange(0, groupName.length)]; - if (!match || match.range.location == NSNotFound) continue; - - [genericItemName appendString:[groupName substringWithRange:[match rangeAtIndex:1]]]; - [genericItemName appendString:@"_"]; - break; - } - - NSAssert(genericItemName.length > 0, @"Did not find group for mesh %@", self.displayName); - - // 2 - add display name, removing all underscores and newlines - NSCharacterSet *illegalSet = [NSCharacterSet characterSetWithCharactersInString:@"\n\r_"]; - [genericItemName appendString:[[self.displayName componentsSeparatedByCharactersInSet:illegalSet] componentsJoinedByString:@"-"]]; - - // 3 - write required parameters - for (NSArray* renderParameterNames in xnaLaraShaderDescription.parameterUniformsInOrder) - { - GLLFloatRenderParameter *param = (GLLFloatRenderParameter *) [self renderParameterWithName:renderParameterNames[0]]; - NSAssert(param && [param isMemberOfClass:[GLLFloatRenderParameter class]], @"Object has to have parameter %@ and it must be float", renderParameterNames[0]); - - [genericItemName appendFormat:@"_%f", param.value]; - } - - return genericItemName; -} - -- (NSArray *)textureUrlsForDescription:(XnaLaraShaderDescription *)xnaLaraShaderDescription -{ - return [xnaLaraShaderDescription.textureUniformsInOrder map:^(NSString *textureName){ - return [self textureWithIdentifier:textureName].textureURL; - }]; -} - -- (NSString *)writeASCIIError:(NSError *__autoreleasing*)error; -{ - XnaLaraShaderDescription *description = [self shaderDescriptionError:error]; - if (!description) return nil; - return [self.mesh writeAsciiWithName:[self genericItemNameForShaderDescription:description] texture:[self textureUrlsForDescription:description]]; -} -- (NSData *)writeBinaryError:(NSError *__autoreleasing*)error; -{ - XnaLaraShaderDescription *description = [self shaderDescriptionError:error]; - if (!description) return nil; - return [self.mesh writeBinaryWithName:[self genericItemNameForShaderDescription:description] texture:[self textureUrlsForDescription:description]]; -} - -- (BOOL)shouldExport -{ - return self.isVisible && ([self shaderDescriptionError:NULL] != nil); -} - -@end diff --git a/GLLara/GLLItemMesh+MeshExport.swift b/GLLara/GLLItemMesh+MeshExport.swift new file mode 100644 index 00000000..a45410fa --- /dev/null +++ b/GLLara/GLLItemMesh+MeshExport.swift @@ -0,0 +1,71 @@ +// +// GLLItemMesh+MeshExport.swift +// GLLara +// +// Created by Torsten Kammer on 25.02.13. +// Copyright (c) 2013 Torsten Kammer. All rights reserved. +// + +import Foundation + +extension GLLItemMesh { + + func shaderDescription() throws -> XnaLaraShaderDescription { + let description = mesh.model?.parameters.xnaLaraShaderDescriptions.first { + if $0.baseName != shaderBase { + return false + } + return Set($0.moduleNames) == shaderModules + } + guard let description = description else { + throw NSError(domain: "GLLMeshExporting", code: 1, userInfo: [ + NSLocalizedDescriptionKey : NSLocalizedString("Could not export model.", comment:"no mesh group found for model to export"), + NSLocalizedRecoverySuggestionErrorKey : String(format: NSLocalizedString("No XNALara Mesh Group number corresponds to the shader %@.", comment: "can't write meshes without tangents"), shaderBase)]) + } + return description + } + + func genericName(shaderDescription: XnaLaraShaderDescription) -> String { + var name = "" + + let possibleGroups = mesh.usesAlphaBlending ? shaderDescription.alphaMeshGroups : shaderDescription.solidMeshGroups + let nameRegex = /^MeshGroup([0-9]+)$/ + for groupName in possibleGroups { + if let match = try? nameRegex.firstMatch(in: groupName) { + name = match.1 + "_" + } + } + assert(!name.isEmpty) + + // 2 - add display name, removing all underscores and newlines + let illegalCharacters = /[\n\r ]/ + name += displayName.replacing(illegalCharacters, with: { _ in "-" }) + + // 3 - write required parameters + for parameterNames in shaderDescription.parameterUniformsInOrder { + let param = renderParameter(withName: parameterNames[0]) as! GLLFloatRenderParameter + name += "_\(param.value)" + } + + return name + } + + func textureUrls(description: XnaLaraShaderDescription) -> [URL] { + return description.textureUniformsInOrder.map { texture(withIdentifier: $0).textureURL } + } + + func writeASCII() throws -> String { + let shaderDescription = try shaderDescription() + return mesh.writeAscii(withName: genericName(shaderDescription: shaderDescription), texture: textureUrls(description: shaderDescription)) + } + + func writeBinary() throws -> Data { + let shaderDescription = try shaderDescription() + return mesh.writeBinary(withName: genericName(shaderDescription: shaderDescription), texture: textureUrls(description: shaderDescription)) + } + + var shouldExport: Bool { + let shaderDescription = try? shaderDescription() + return isVisible && shaderDescription != nil + } +} diff --git a/GLLara/GLLVertexAttrib.h b/GLLara/GLLVertexAttrib.h index 29186095..9940f6a4 100644 --- a/GLLara/GLLVertexAttrib.h +++ b/GLLara/GLLVertexAttrib.h @@ -6,7 +6,7 @@ // Copyright © 2021 Torsten Kammer. All rights reserved. // -#ifndef __METAL_MACOS__ +#ifndef __METAL__ #import diff --git a/GLLara/GLLara-Bridging-Header.h b/GLLara/GLLara-Bridging-Header.h index fb42ca25..4857e488 100644 --- a/GLLara/GLLara-Bridging-Header.h +++ b/GLLara/GLLara-Bridging-Header.h @@ -11,6 +11,7 @@ #import "GLLDirectionalLight.h" #import "GLLDocument.h" #import "GLLDocumentWindowController.h" +#import "GLLFloatRenderParameter.h" #import "GLLItem.h" #import "GLLItemBone.h" #import "GLLItemMesh.h"