I have a command plugin that can successfully generate files and put them into by an Xcode project folder where I want them to be. It is a twin to a ProjectPlugin that does a similar task.
Currently I manually add the generated files to the project using using "File > Add Files to..."
That isn't that hard, but is there a way to add the file to the project programmatically? It would be handy to make it more on par with the end state of running the command on a package.
Thanks!
Post
Replies
Boosts
Views
Activity
The Apple documentation seems to say RealityKit should obey the autoplay metadata, but it doesn't seem to work. Is the problem with my (hand coded) USDA files, the Swift, or something else? Thanks in advance.
I can make the animations run with an explicit call to run, but what have I done wrong to get the one cube to autoplay?
https://github.com/carlynorama/ExploreVisionPro_AnimationTests
import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
@State var enlarge = false
var body: some View {
VStack {
//A ModelEntity, not expected to autoplay
Model3D(named: "cube_purple_autoplay", bundle: realityKitContentBundle)
//An Entity, actually expected this to autoplay
RealityView { content in
if let cube = try? await Entity(named: "cube_purple_autoplay", in: realityKitContentBundle) {
print(cube.components)
content.add(cube)
}
}
//Scene has one cube that should auto play, one that should not.
//Neither do, but both will start (as expected) with click.
RealityView { content in
// Add the initial RealityKit content
if let scene = try? await Entity(named: "Scene", in: realityKitContentBundle) {
content.add(scene)
}
} update: { content in
// Update the RealityKit content when SwiftUI state changes
if let scene = content.entities.first {
if enlarge {
for animation in scene.availableAnimations {
scene.playAnimation(animation.repeat())
}
} else {
scene.stopAllAnimations()
}
let uniformScale: Float = enlarge ? 1.4 : 1.0
scene.transform.scale = [uniformScale, uniformScale, uniformScale]
}
}
.gesture(TapGesture().targetedToAnyEntity().onEnded { _ in
enlarge.toggle()
})
VStack {
Toggle("Enlarge RealityView Content", isOn: $enlarge)
.toggleStyle(.button)
}.padding().glassBackgroundEffect()
}
}
}
No autospin meta data
#usda 1.0
(
defaultPrim = "transformAnimation"
endTimeCode = 89
startTimeCode = 0
timeCodesPerSecond = 24
upAxis = "Y"
)
def Xform "transformAnimation" ()
{
def Scope "Geom"
{
def Xform "xform1"
{
float xformOp:rotateY.timeSamples = {
...
}
double3 xformOp:translate = (0, 0, 0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateY"]
over "cube_1" (
prepend references = @./cube_base_with_purple_linked.usd@
)
{
double3 xformOp:translate = (0, 0, 0)
uniform token[] xformOpOrder = ["xformOp:translate"]
}
}
With autoplay metadata
#usda 1.0
(
defaultPrim = "autoAnimation"
endTimeCode = 89
startTimeCode = 0
timeCodesPerSecond = 24
autoPlay = true
playbackMode = "loop"
upAxis = "Y"
)
def Xform "autoAnimation"
{
def Scope "Geom"
{
def Xform "xform1"
{
float xformOp:rotateY.timeSamples = {
...
}
double3 xformOp:translate = (0, 0, 0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateY"]
over "cube_1" (
prepend references = @./cube_base_with_purple_linked.usd@
)
{
quatf xformOp:orient = (1, 0, 0, 0)
float3 xformOp:scale = (2, 2, 2)
double3 xformOp:translate = (0, 0, 0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
}
}
}
}
I am working on a Server-Sent-Event parser which has newlines as part of the protocol:
https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
If the line is empty (a blank line)
Dispatch the event, as defined below.
Unfortunately, when using:
let (asyncBytes, _) = try await self.session.bytes(from: sseStreamURL)
for try await line in asyncBytes.lines {
//parse line
}
The iterator actually skips empty lines entirely, which seems destructive and therefore can't be the only way? Can it? With split there is a omittingEmptySubsequences: false, but I didn't find any trace of anything like that for .lines. I couldn't find the var definition in the Swift repo either, if anyone could point me at it.
I did write something that works for now, but I'd love if anyone had any comments on how to improve it / point me at any exiting language features that I missed.
extension AsyncSequence where Element == UInt8 {
var allLines:AsyncThrowingStream<String, Error> {
AsyncThrowingStream { continuation in
Task {
var buffer:[UInt8] = []
var iterator = self.makeAsyncIterator()
while let byte = try await iterator.next() {
// b/c 10 == \n
if byte != 10 { buffer.append(byte) }
else {
if buffer.isEmpty { continuation.yield("") }
else {
if let line = String(data: Data(buffer), encoding: .utf8) { continuation.yield(line) }
else {
//Is there a different AsyncSequence error I could use?
throw SSEError("allLines: Couldn't make string from [UInt8] chunk")
}
buffer = []
}
}
}
}
}
}
}
usage:
for try await line in asyncBytes.allLines {
//parse line
}
or of course also
var iterator = asyncBytes.allLines.makeAsyncIterator()
while let line = try await iterator.next() {
//parse line
}
I am running into an example where if you have a View that has a NavigationStack in it, and it appears and disappears based on a conditional, it doesn't seem to get fully torn down?
This appears to matter most when it is also initializing a ViewModel, because it will reinit without deiniting.
So for example
struct ContentView: View {
@State var showNavStack:Bool = false
var body: some View {
Button("ShowHide") {
showNavStack.toggle()
}.padding(20)
if showNavStack {
SimpleRootView()
}
}
}
With the NavigationStack view
import SwiftUI
class DoNothingVM:ObservableObject {
deinit {
print("ViewModel DEINIT")
}
init() {
print("ViewModel INIT")
}
}
struct SimpleRootView: View {
@StateObject var viewModel = DoNothingVM()
@State var path = NavigationPath()
let int = Int.random(in: 0...100)
var body: some View {
NavigationStack(path: $path) {
VStack {
Text("Hello \(int)")
Button("Go Forward") {
path.append(Int.random(in: 0...100))
}
}.navigationDestination(for: Int.self) { int in
DetailIntView(int: int, path: $path)
}.navigationTitle("\(int)")
}
}
}
struct DetailIntView:View {
let int:Int
@Binding var path:NavigationPath
var body: some View {
VStack {
Text("Hello \(int)")
Button("Go Forward") {
path.append(Int.random(in: 0...100))
}
}.navigationTitle("\(int)")
}
}
Will lead to multiple calls to a DoNothing init every time the showNavStack is toggled to true, but no deinit when toggled to false. Multiples remain in memory.
"So don't do that" is fine for me in my case, but I'm wondering if this is expected behavior? Is it simply that SwiftUI only expects One and Only One NavigationStack per app and that it will be the only thing in charge? I haven't tested it, but what does that mean for coming back out of the background? This seems like a bug, but it might also be my misunderstanding.
Project where I'm messing around with this here: https://github.com/carlynorama/NavigationExplorer
Summary: The "ProfitOverTime" example code from https://developer.apple.com/documentation/charts/chart does not compile, and when changes are made to make it compile the chart concatenates the lines rather than having them be separate.
Seen in Xcode-Beta's 14.3 and 14. 4 (14A5284g)
Is it simply that this method of layering lines is deprecated already?
When trying to have a chart with multiple data sets, I copy-pasted the code from the above link and generated the appropriate placeholder data. I got an error that ProfitOverTime was not identifiable, so I added the id on date.
In both the case of the years being identical and of the years being different the lines concatenate instead of overlay like in the screenshot on the docs page.
Is this method of multiple lines still available and I'm just doing it wrong?
Is only method to have multiple lines series as seen on the LineMark docs page?
struct ChartTests: View {
struct ProfitOverTime {
var date: Date
var profit: Double
}
static func months(forYear year:Int) -> [Date] {
var days:[Date] = []
var dateComponets = DateComponents()
//let year = Calendar.current.component(.year, from: Date())
dateComponets.year = year
dateComponets.day = 1
for i in 1...12 {
dateComponets.month = i
if let date = Calendar.current.date(from: dateComponets) {
days.append(date)
}
}
return days
}
static func dataBuilder(forYear year:Int) -> [ProfitOverTime]{
var data:[ProfitOverTime] = []
for month in months(forYear: year) {
let new = ProfitOverTime(date: month, profit: Double.random(in: 200...600))
data.append(new)
}
return data
}
let departmentAProfit: [ProfitOverTime] = Self.dataBuilder(forYear: 2021)
let departmentBProfit: [ProfitOverTime] = Self.dataBuilder(forYear: 2021)
var body: some View {
Chart {
ForEach(departmentAProfit, id: \.date) {
LineMark(
x: .value("Date", $0.date),
y: .value("Profit A", $0.profit)
)
.foregroundStyle(.blue)
}
ForEach(departmentBProfit, id: \.date) {
LineMark(
x: .value("Date", $0.date),
y: .value("Profit B", $0.profit)
)
.foregroundStyle(.green)
}
RuleMark(
y: .value("Threshold", 500.0)
)
.foregroundStyle(.red)
}
}
}
struct ChartTests_Previews: PreviewProvider {
static var previews: some View {
ChartTests()
}
}