I made scene: part is defined in a .scn file, bunch of boxes are added progamatically. But after export to .dae, generated boxes are broken: each side has only one triangle, half of side is empty. Also it's impossible to import this file to Blender. Blender quits. Any ideas?
Post
Replies
Boosts
Views
Activity
Good (morning, evening...).
I try to build SwiftUI view hierarchy for model where:
I have many Glyph objects: var manager: CoordinatesManager
var elements: [ ManyMultidimensionalElements ]
var path: Path { return Path(..based on elements and manager.currentCoordinates) }
I have one CoordinatesManger: var currentCoordinates: [ Coordinate ]
In one view I can set currrentCoordinates of CoordinatesManager, in second view I want to see Glyph with actual glyph.manager.currentCoordinates
It almost works but:changing manager.currentCoordinates doesn't change GlyphView, even if Glyph object see manager.currentCoordinates was changed (in manger.didSet{...})
When scrolling (why?) glyph.path is recalculated, but View stays untouched.
Example Playground - https://developer.apple.com/forums/content/attachment/507e87de-2094-4998-8361-b3c1dd21549c
How to push View to redraw? Something like NSView.needsDisplay. How to trigger View to redraw, when glyph.manager.currentCoordinates are changed?
PS. It's my first post on this forum, I don't know what's the best: hide Playground file as attachment or list it in main text.
I have a struct:public typealias CoordUnit = Double
public struct StyledAxis: StyledAxisProtocol {
		public var name: String
		public var bounds: ClosedRange<CoordUnit>
		public var distribution: Double?
...
}
In SpaceAxisProtocol bounds are defined as:
		public protocol SpaceAxisProtocol: Equatable & Hashable {
				var name: String {get set}
				var bounds: ClosedRange<CoordUnit> {get set}
			 init(_ name: String, bounds: ClosedRange<CoordUnit>)
		}
		public protocol StyledAxisProtocol: SpaceAxisProtocol {...}
And I try to edit bounds in a View:
		struct StyledAxisView<SA:StyledAxisProtocol>: View {
				@Binding var axis: SA
				
				public var body : some View {
						VStack {
								// Axis name and distribution works
								HStack(alignment: .lastTextBaseline) {
										TextField("", text: $axis.name)
												.controlSize(.small)
												.font(.headline)
										
										DistributionView(
												value: $axis.distribution)
												.controlSize(.mini)
								}
								// It causes compiler `Cannot assign to property: 'lowerBound' is a 'let' constant`. But it isn't. ?
								HStack {
										ValueView(value: $axis.bounds.lowerBound)
										ValueView(value: $axis.bounds.upperBound)
								}
								...
When axis.bounds.lowerbound and axis.bounds.upperbound became let? How to edit them in View?
I try to build an app in MacOS SwiftUI, where two different subviews of main contentView shows different parts of Axis element:struct ContentView: View {
		@Binding var document: GlyphDesignerDocument
		
		var body: some View {
				HStack {
						//Axes Sliders Slider causes explosion
AxesSlidersView(axes: $document.axes)
AxesView(axes: $document.axes,
addRows: {document.axes.insert(Axis("z", bounds: 0...1000), at: $0)},
removeRows: {document.axes.remove(at: $0)},
addAxis: {document.axes.append(Axis("z", bounds: 0...1000))})
}
}
Subviews works great, everything updates in both ways, but application hangs-up when AxisView will delete one Axis from axes array.
All experimental code (still changing) is available at https://github.com/typoland/GlyphDesignerTest
AxesView looks like this:
		struct AxesView : View {
				@Binding var axes: [Axis]
				@State var selected: Int? = nil
				var addRows: (_ at:Int) -> Void
				var removeRows: (_ at: Int) -> Void
				var addAxis: () -> Void
				var body: some View {
						VStack {
								.... Shows Axes
						}
				}
		}
		struct AxisView: View {
				
				@Binding var axis: Axis
				var insert: () -> Void
				var delete: () -> Void
				@Binding var selected: Bool
				
				var body: some View {
						HStack {
							 //Makes ForEach for each Axis, adds buttons to insert and delete, more parameters of an Axis...
						}
				}
		}
		struct AxesSlidersView: View {
				@Binding var axes: [Axis]
				var body: some View {
						VStack {
								ForEach(axes.indices, id:\.self) {index in
		HStack {
												 Text("\(axis.name)")
													Slider (value: $axes[index].at, in: axis.bounds)
		 }
}
						}
				}
		}
		
After suggestion received on stackoverflow I changed:
Slider (value: $axes[index].at, in: axis.bounds)
to
Slider (value: Bound(get: {axis.ataxes[index].at}, set: {axes[index].at = $0}, in: axis.bounds)
This way I can delete axis without explosion, but, second view does not live update anymore.
Is it SwiftUI problem? How to deal with this? @Binding arrays is somehow broken?
Maybe I missed something — is it possible to somehow edit / change / customise main menu in SwiftUI App lifecycle? I made a document based App, I can read, write, even Recent Documents have for free. But how to add or remove Items, and connect them with app in pure SwiftUI way? With no AppKit, pure?
I'm trying to learn how UndoManager works. I made a small app to Undo/Redo something.
And I have few questions, I cannot find answer in documentation:
I know UndoManager could be accessed in View via
@Environment(\.undoManager) var undoManager
Brilliant. But in this case it's only available in a View, if I want use it somewhere deeper in a structure I have to pass it via Model to Objects... Is a way to access the same UndoManager in other objects? Models, Data... I could be much more convenient, specially if there is many Undo groupings. If I create UndoManager in Document (or somewhere else) it's not visible for main menu Edit -> Undo, Redo
In the app repository on GitHub I implemented Undo/Redo. For me (haha) it looks OK and even works, but not for first action. First action Undo causes Thread 1: signal SIGABRT error. After three actions I can undo two last actions... Bang. Something is wrong
import Foundation
import SwiftUI
struct CustomView: View {
@ObservedObject var model: PointsViewModel
@Environment(\.undoManager) var undoManager
@GestureState var isDragging: Bool = false
@State var dragOffsetDelta = CGPoint.zero
var formatter: NumberFormatter {
let formatter = NumberFormatter()
formatter.allowsFloats = true
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 5
return formatter
}
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 10) {
ForEach(model.insideDoc.points.indices, id:\.self) { index in
HStack {
TextField("X", value: $model.insideDoc.points[index].x, formatter: formatter)
.frame(width: 80, alignment: .topLeading)
TextField("Y", value: $model.insideDoc.points[index].y, formatter: formatter)
.frame(width: 80, alignment: .topLeading)
Spacer()
}
}
Spacer()
}
ZStack {
ForEach(model.insideDoc.points.indices, id:\.self) { index in
Circle()
.foregroundColor(index == model.selectionIndex ? .red : .blue)
.frame(width: 20, height: 20, alignment: .center)
.position(model.insideDoc.points[index])
//MARK: - drag point
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged { drag in
if !isDragging {
dragOffsetDelta = drag.location - model.insideDoc.points[index]
model.selectionIndex = index
let now = model.insideDoc.points[index]
undoManager?.registerUndo(withTarget: model, handler: { model in
model.insideDoc.points[index] = now
model.objectWillChange.send()
})
undoManager?.setActionName("undo Drag")
}
model.insideDoc.points[index] = drag.location - dragOffsetDelta
}
.updating($isDragging, body: { drag, state, trans in
state = true
model.objectWillChange.send()
})
.onEnded({drag in model.selectionIndex = index
model.insideDoc.points[index] = drag.location - dragOffsetDelta
model.objectWillChange.send()
})
)
}
}.background(Color.orange.opacity(0.5))
//MARK: - new point
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onEnded{ loc in
let previousIndex = model.selectionIndex
undoManager?.registerUndo(withTarget: model, handler: {model in
model.insideDoc.points.removeLast()
model.selectionIndex = previousIndex
model.objectWillChange.send()
})
model.insideDoc.points.append(loc.location)
model.selectionIndex = model.insideDoc.points.count - 1
model.objectWillChange.send()
}
)
//MARK: - delete point
.onReceive(deleteSelectedObject, perform: { _ in
if let deleteIndex = model.selectionIndex {
let deleted = model.insideDoc.points[deleteIndex]
undoManager?.registerUndo(withTarget: model, handler: {model in
model.insideDoc.points.insert(deleted, at: deleteIndex)
model.objectWillChange.send()
})
undoManager?.setActionName("remove Point")
model.insideDoc.points.remove(at: deleteIndex)
model.objectWillChange.send()
model.selectionIndex = nil
}
})
}
}
}
Any comments about quality of my algorithms will be highly appreciated.
As in a title: even empty new app has menu with working menu items, but with disabled and not working keyboard shortcuts. Is it bug, feature or I should do something to enable them?
Minimize, Zoom... works.
My Edit Menu have the same problem:
Commands Undo, Redo and Delete works when chosen from menu, but calling them via keyboard causes only cursor disappear.
I have a ZStack view embedded in ScrollView. The height of ZStack often changes.
var body: some View {
ScrollView([.vertical, .horizontal], showsIndicators: true) {
VStack { // embedding in VStack doesn't change behaviour
ZStack () {
ForEach(mapElements.indices, id:\.self) { i in
let element = mapElements[i]
MapElementView (mapElement: element)
.position(x: offset(x: element.x),
y: offset(y: element.y))
.zIndex(5)
MakeConnections(mapElement: element)
}
}.frame(width: calculateWidth(),
height: calculateHeight())
}
Rectangle() // Just to make VStack filled
}
}.frame(alignment: .topLeading)
}
Some scroll views (ie. list) always align embedded objects to top even they are shorter than embedding scroll view. But in this case ZStack is always centred when view is refreshed.
Is it possible to define behaviour, so each change of a content will align its top to scroll view top, even if height of ZStack is smaller than ScrollView?
I have a VSplitView with two views inside. But each time app starts proportions are set to 50/50, each one has the same height. I would like to set height of one of them to some number, (and save it in defaults... not most important thing). Of course I would like to change this height manually if I need to.
var body: some View {
return VSplitView {
HigherView(with: someContent) // Let it be float height
ShorterView(with: anotheContent) // let it height will be 300 when fired first time
}
}
Is it very hard?
I build a graphic editor. Dragging points through my canvas is smooth and fast. But when I try to display data in outline view everything slows down to 2 FPS. First I suspected slow data access, but when I check app in Instruments I found Core Animation Commits are displayed as a red blocks and Time Profiler bit busy.
Is a way to disable Core Animation for some views? Or this message is misleading?
I have a MacOS app which has a lot of TextFields in many views; and one editor view which has to receive pressed keyboard shortcut, when cursor is above. But as I try, I cannot focus on a view which is not text enabled. I made a small app to show a problem:
@main
struct TestFocusApp: App {
var body: some Scene {
DocumentGroup(newDocument: TestFocusDocument()) { file in
ContentView(document: file.$document)
}
.commands {
CommandGroup(replacing: CommandGroupPlacement.textEditing) {
Button("Delete") {
deleteSelectedObject.send()
}
.keyboardShortcut(.delete, modifiers: [])
}
}
}
}
let deleteSelectedObject = PassthroughSubject<Void, Never>()
struct MysticView: View {
var body: some View {
ZStack {
Rectangle()
.foregroundColor(.gray.opacity(0.3))
}.focusable()
.onReceive(deleteSelectedObject) { _ in
print ("received")
}
}
}
enum FocusableField {
case wordTwo
case view
case editor
case wordOne
}
struct ContentView: View {
@Binding var document: TestFocusDocument
@State var wordOne: String = ""
@State var wordTwo: String = ""
@FocusState var focus: FocusableField?
var body: some View {
VStack {
TextField("one", text: $wordOne)
.focused($focus, equals: .wordOne)
TextEditor(text: $document.text)
.focused($focus, equals: .editor)
///I want to receive DELETE in any way, in a MystickView or unfocus All another text views in App to not delete their contents
MysticView()
.focusable(true)
.focused($focus, equals: .view)
.onHover { inside in
focus = inside ? .view : nil
/// focus became ALWAYS nil, even set to `.view` here
}
.onTapGesture {
focus = .view
}
TextField("two", text: $wordTwo)
.focused($focus, equals: .wordTwo)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(document: .constant(TestFocusDocument()))
}
}
Only first TextField became focused when I click or hover over MysticView
I can assign nil to focus, but it will not unfocus fields from outside this one view.
Is it a bug, or I missed something? How to make View focusable? To Unfocus all textFields?
I have a MacOS package dependency which defines some class: FontPens
import Foundation
...
public class BoundsPen: Pen {
var bounds = CGRect.null
private var currentPoint = CGPoint.zero
....
After upgrading Xcode to 14.1 both lines throws errors Type 'CGRect' has no member 'null' and Type 'CGPoint' has no member 'zero'.
Calling CGPoint.zero and CGRect.null from an app is OK if Foundation is imported.
Is it a way to solve this problem without changing package source?
I have a view, and in this view I bind Axis class values — lowerBound which is a regular property and at – computed one which comes from protocol HasPositionProtocol associated with Axis.
struct AxisPropertiesView<Axis>: View
where Axis: StyledAxisProtocol,
Axis: HasPositionProtocol,
Axis: Observable
{
@Bindable var axis: Axis
var body: some View {
HStack {
TextField("", text: $axis.shortName)
.frame(width: 40)
TextField("",
value: $axis.lowerBound,
format: .number)
.frame(width: 45)
//Problem is here:
Slider(value: $axis.at,
in: axis.bounds)
...
Unfortunately I got en error Failed to produce diagnostic for expression; ... for whole View.
But if I remove Slider from View, error disappeared.
What could cause this strange behaviour?
Value of .at comes from:
public extension HasPositionProtocol {
///Absolut position on Axis
var at: Double {
get {
switch position {
case .max:
return bounds.upperBound
case .min:
return bounds.lowerBound
case .number(let number):
return number
}
}
set {
switch newValue {
case bounds.lowerBound:
position = .min
case bounds.upperBound:
position = .max
default:
position = .number(newValue)
}
}
}
}
I try to generate PDF from view. View is nice, there is a lot of transparency and many gradients (circular and linear). But if I use ImageRenderer in in a way that documentation suggest all transparency and gradients disappear. Is this bug or some feature? Is it way to generate vector graphic from view with transparency and gradients? PDF allows those features, so why not?
I try to convert view to vector graphic (PDF) using ImageRenderer. But output image has ALL coordinates rounded to integer values, which is not OK - some very small circles become elipses, squares are no longer squares, very detailed or small shapes are distorted by rounding coordinates. Is a some option to switch off rounding?