rust egui, geoemtry isn't clipped - user-interface

I am trying to use egui with a custom renderer I made. I am rendering to the screen, but it looks like this:
i.e. the widget occupies the entire screen. When I inspect the data I get from egui
let output = self.ctx.run(raw_input, |ctx|
{
egui::CentralPanel::default().show(&ctx, |ui| {
ui.label("Hello world!");
if ui.button("Click me").clicked() {
// take some action here
}
});
});
let clipped_primitives = self.ctx.tessellate(output.shapes);
for primitive in clipped_primitives
{
println!("{:?}", primitive.clip_rect);
/* render */
}
I get:
[[0.0 0.0] - [800.0 800.0]]
[[0.0 0.0] - [800.0 800.0]]
[[0.0 0.0] - [800.0 800.0]]
[[0.0 0.0] - [800.0 800.0]]
[[0.0 0.0] - [800.0 800.0]]
[[0.0 0.0] - [800.0 800.0]]
[[0.0 0.0] - [800.0 800.0]]
Why arent the primitives clipped?

The answer is to use a Window container instead of a CentralPanel

Related

Programmatically overlay image on gradient

I’m building out a UI that has a few screens with a gradient background and a tiled PNG (blend mode: multiply # 9% opacity) on top to create noise.
I've managed to create the gradient programatically with this snippet I found here but I'm struggling to figure out how to edit this to add the PNG over it
import Foundation
import UIKit
#IBDesignable class DarkGradient: UIView {
let titleLabel = UILabel()
#IBInspectable var title: String? = nil {
didSet {
titleLabel.text = title
}
}
override func layoutSubviews() {
super.layoutSubviews()
// Necessary in layoutSubviews to get the proper frame size.
configure()
}
func configure() {
let gradient = CAGradientLayer()
gradient.frame = bounds
gradient.colors = [UIColor(red: 0.16, green: 0.0, blue: 0.54, alpha: 1).cgColor,
UIColor(red: 0.26, green: 0.0, blue: 0.88, alpha: 1).cgColor]
gradient.startPoint = CGPoint(x: -0.5, y: 0.5)
gradient.endPoint = CGPoint(x: 0.5, y: 1.5)
layer.insertSublayer(gradient, at: 0)
}
}
Grateful for any help, all the answers I've found have been overlaying gradients over images.

CoreGraphice Stroke Text with Gradient

With the help of CGContextSetTextDrawingMode we are able to draw bordered Text. How can we fill the border with a brush (Gradient/Picture) instead of a solid color?
Can't find this on Apple Docs.
by using context.addPath(path) , then context.clip(to: pathFrame)
then you can use context.drawLinearGradient
in order to draw without side effects,
remember to use context.saveGState() and context.restoreGState(),
Here is an example for iOS version,
you should edit it to MacOS version
class CustomV: UIView{
override func draw(_ rect: CGRect) {
// Create a gradient from white to red
let colors: [CGFloat] = [
1.0, 1.0, 1.0, 1.0,
1.0, 0.0, 0.0, 1.0]
let baseSpace = CGColorSpaceCreateDeviceRGB()
guard let context = UIGraphicsGetCurrentContext(), let gradient =
CGGradient(colorSpace: baseSpace, colorComponents: colors, locations: nil, count: 2) else{ return }
context.saveGState()
let offset: CGFloat = 10
let startPoint = CGPoint(x: rect.maxX - offset, y: rect.minY)
let endPoint = CGPoint(x: rect.maxX - offset, y: rect.maxY)
let p = CGMutablePath()
p.move(to: startPoint)
p.addLine(to: endPoint)
context.addPath(p)
context.clip(to: CGRect(origin: startPoint, size: CGSize(width: 3, height: 800)))
context.setLineWidth(offset)
context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: [])
context.restoreGState()
}
}

iOS10 - can't render Sprite Kit scene within SceneKit with openGL

Since I've updated to iOS 10, I'm not able anymore to render a Sprite Kit scene to a Scene Node while using openGL for rendering. Things work fine with Metal. The error logs: "Failed to create IOSurface image (texture)"
I used to be able to do something like:
class ViewController: UIViewController {
#IBOutlet weak var scnView: SCNView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
scnView.showsStatistics = true
scnView.allowsCameraControl = true
let scnScene = SCNScene()
scnView.scene = scnScene
print("scnView renderingAPI is metal", scnView.renderingAPI == SCNRenderingAPI.metal)
print("scnView renderingAPI is opengl", scnView.renderingAPI == SCNRenderingAPI.openGLES2)
// setup SceneKit scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0.0, y: 0.0, z: 25.0)
scnScene.rootNode.addChildNode(cameraNode)
let cubeNode = SCNNode()
cubeNode.geometry = SCNBox(width: 5.0, height: 5.0, length: 5.0, chamferRadius: 0.0)
scnScene.rootNode.addChildNode(cubeNode)
// setup SpriteKit Scene
let skScene = SKScene()
skScene.backgroundColor = UIColor.black
skScene.size = CGSize(width: 100, height: 100)
let skNode = SKShapeNode(rect: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0))
skNode.fillColor = UIColor.green
skNode.position = CGPoint(x: 5.0, y: 5.0)
skScene.addChild(skNode)
cubeNode.geometry?.firstMaterial?.diffuse.contents = skScene
}
}
(here is a repo to reproduce this: https://github.com/gsabran/iOS10-OpenGLRenderingBug)

When creating a custom View in Swift, how can you draw on top of the current context from outside the drawRect function?

I'm trying to create bullet points that can be filled in with a:
fillCircle
function, but I found out that the only way to successfully do this is to pass the context from the drawRect function.
My class is set up so that first it draws the empty bullets with the drawRect function, as seen here:
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
CGContextSetLineCap(context, kCGLineCapButt)
bulletColor.set()
for i in 1...numberOfBullets{
CGContextAddArc(context, CGFloat(Float(i) * Float(bulletSpacing)), self.frame.size.height/2, radius, 0, CGFloat(2 * M_PI), 0)
CGContextDrawPath(context, kCGPathStroke)
}
}
I'm trying to implement a fillCircle function like so:
func fillCircle(context: CGContextRef, circleNumber: Int){
CGContextFillEllipseInRect(context, CGRect(x: CGFloat(circleNumber) * (bulletSpacing) - radius, y: self.frame.size.height/2 - radius, width: 2*radius, height: 2*radius))
CGContextDrawPath(context, kCGPathStroke)
}
So that any users of the class can fill in bullets at will, but I can't seem to get the context from outside of drawrect. I can't pass in the context from drawRect because then it would be called every time the class is created.
How can i implement a fillCircle method without altering drawRect?
Why can't you redraw it when a new bullet point is added? You can use setNeedsDisplay function for that. Store a new variable indicating the number of lines with filled bullet point, numberOfFilledBullets.
setNeedsDisplay redraws the view and calls drawRect again.
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
CGContextSetLineCap(context, kCGLineCapButt)
bulletColor.set()
for i in 1...numberOfBullets{
CGContextAddArc(context, CGFloat(Float(i) * Float(bulletSpacing)), self.frame.size.height/2, radius, 0, CGFloat(2 * M_PI), 0)
CGContextDrawPath(context, kCGPathStroke)
}
for i in 1...numberOfFilledBullets {
// fillCircle
CGContextFillEllipseInRect(context, CGRect(x: CGFloat(i) * (bulletSpacing) - radius, y: self.frame.size.height/2 - radius, width: 2*radius, height: 2*radius))
CGContextDrawPath(context, kCGPathStroke)
}
}
func addNewLine {
numberOfFilledBullets ++
self.setNeedsDisplay()
}
func deleteLine {
numberOfFilledBullets --
self.setNeedsDisplay()
}

Swift Playground XCPShowView "Unable to satisfy constraints"

I'm trying to get a Live View to show a simple animation in a Swift Playground. Whenever I import the XCPlayground framework to execute the XCPShowView function i get this error:
Playground execution failed: error: Couldn't lookup symbols:_CGPointMake
The error changes for a few other "symbols" as well, including CGRectMake.
After being advised to modifying my code to remove the "make" from methods such as CGRectMake I still get an error from Xcode when I try to animate my view. The error message is really long, but basically it says
"Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want."
Here is the code I am trying to work with:
//Circle Button
class timerButtonGraphics: UIView {
override func drawRect(rect: CGRect) {
let colorGreen = UIColor(red: 0.310, green: 0.725, blue: 0.624, alpha: 1.000)
let colorRed = UIColor(red: 241/255, green: 93/255, blue: 79/255, alpha: 100)
var bounds = self.bounds
var center = CGPoint()
center.x = bounds.origin.x + bounds.size.width / 2
center.y = bounds.origin.y + bounds.size.height / 2
var radius = 61
var path:UIBezierPath = UIBezierPath()
path.addArcWithCenter(center, radius: CGFloat(radius), startAngle: CGFloat(0.0), endAngle: CGFloat(Float(M_PI) * 2.0), clockwise: true)
path.strokeWithBlendMode(kCGBlendModeNormal, alpha: 100)
path.lineWidth = 2
if strokeRed == true {
colorRed.setStroke()
}
else {
colorGreen.setStroke()
}
path.stroke()
}
var strokeRed = true
}
var test = timerButtonGraphics(frame: CGRect(x: 0, y: 400, width: 400, height: 400))
UIView.animateWithDuration(2.0, delay: 2, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: nil, animations: {
test.transform = CGAffineTransformMakeTranslation(0.5, 0)
}, completion: nil)
XCPShowView("Circle Animation", test)
try with this, maybe it can help you
test.setTranslatesAutoresizingMaskIntoConstraints(false)

Resources