[kit] Pass target and feather values into the shaders
This commit is contained in:
parent
6c06aadd37
commit
0b752984dc
4 changed files with 134 additions and 20 deletions
|
@ -293,6 +293,17 @@ public class Field {
|
|||
didChange = true
|
||||
}
|
||||
|
||||
if let target = userInfo["target"] as? Float {
|
||||
parameters.target = target
|
||||
defaults.target = target
|
||||
didChange = true
|
||||
}
|
||||
if let feather = userInfo["feather"] as? Float {
|
||||
parameters.feather = feather
|
||||
defaults.feather = feather
|
||||
didChange = true
|
||||
}
|
||||
|
||||
if didChange {
|
||||
populateParametersBuffer()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,36 @@
|
|||
import Cocoa
|
||||
|
||||
extension UserDefaults {
|
||||
public var target: Float {
|
||||
get {
|
||||
if let obj = object(forKey: "target") as? NSNumber {
|
||||
return obj.floatValue
|
||||
} else {
|
||||
let defaultValue: Float = 1.0
|
||||
set(defaultValue, forKey: "target")
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
set {
|
||||
set(newValue, forKey: "target")
|
||||
}
|
||||
}
|
||||
|
||||
public var feather: Float {
|
||||
get {
|
||||
if let obj = object(forKey: "feather") as? NSNumber {
|
||||
return obj.floatValue
|
||||
} else {
|
||||
let defaultValue: Float = 0.25
|
||||
set(defaultValue, forKey: "target")
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
set {
|
||||
set(newValue, forKey: "feather")
|
||||
}
|
||||
}
|
||||
|
||||
public var colorStyle: ColorStyle? {
|
||||
get {
|
||||
let value = integer(forKey: "colorStyle")
|
||||
|
|
|
@ -39,6 +39,34 @@ public class PreferencesViewController: NSViewController {
|
|||
private var colorStackView = NSStackView()
|
||||
private var colorViews = [ColorView]()
|
||||
|
||||
private lazy var targetSlider: SliderView = {
|
||||
let targetSlider = SliderView(label: NSLocalizedString("Target", comment: "name of the target slider"))
|
||||
targetSlider.slider.tag = Slider.target.rawValue
|
||||
if #available(OSX 10.12.2, *) {
|
||||
targetSlider.slider.trackFillColor = nil
|
||||
}
|
||||
targetSlider.slider.minValue = 0
|
||||
targetSlider.slider.maxValue = 1
|
||||
targetSlider.slider.target = self
|
||||
targetSlider.slider.action = #selector(PreferencesViewController.sliderDidUpdate(sender:))
|
||||
targetSlider.slider.floatValue = self.defaults.target
|
||||
return targetSlider
|
||||
}()
|
||||
|
||||
private lazy var featherSlider: SliderView = {
|
||||
let featherSlider = SliderView(label: NSLocalizedString("Feather", comment: "name of the feather slider"))
|
||||
featherSlider.slider.tag = Slider.feather.rawValue
|
||||
if #available(OSX 10.12.2, *) {
|
||||
featherSlider.slider.trackFillColor = nil
|
||||
}
|
||||
featherSlider.slider.minValue = 0
|
||||
featherSlider.slider.maxValue = 1
|
||||
featherSlider.slider.target = self
|
||||
featherSlider.slider.action = #selector(PreferencesViewController.sliderDidUpdate(sender:))
|
||||
featherSlider.slider.floatValue = self.defaults.feather
|
||||
return featherSlider
|
||||
}()
|
||||
|
||||
private lazy var styleMenu: NSPopUpButton = {
|
||||
let button = NSPopUpButton()
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
@ -100,13 +128,15 @@ public class PreferencesViewController: NSViewController {
|
|||
|
||||
colorStackView.addArrangedSubview(styleMenu)
|
||||
for i in 0..<4 {
|
||||
let colorView = ColorView()
|
||||
let colorView = ColorView(label: "Color \(i+1)")
|
||||
colorView.translatesAutoresizingMaskIntoConstraints = false
|
||||
colorView.label.stringValue = "Color \(i+1)"
|
||||
colorStackView.addArrangedSubview(colorView)
|
||||
colorViews.append(colorView)
|
||||
}
|
||||
|
||||
colorStackView.addArrangedSubview(targetSlider)
|
||||
colorStackView.addArrangedSubview(featherSlider)
|
||||
|
||||
showCloseButtonIfNeeded()
|
||||
|
||||
self.view = view
|
||||
|
@ -163,6 +193,10 @@ public class PreferencesViewController: NSViewController {
|
|||
postColorNotification()
|
||||
}
|
||||
|
||||
func sliderDidUpdate(sender: NSSlider) {
|
||||
postColorNotification()
|
||||
}
|
||||
|
||||
func closeWindow() {
|
||||
self.view.window?.close()
|
||||
}
|
||||
|
@ -191,23 +225,30 @@ public class PreferencesViewController: NSViewController {
|
|||
for (idx, cv) in colorViews.enumerated() {
|
||||
info["color\(idx)"] = cv.colorWell.color
|
||||
}
|
||||
info["target"] = targetSlider.slider.floatValue
|
||||
info["feather"] = featherSlider.slider.floatValue
|
||||
NotificationCenter.default.post(name: PreferencesDidChange_Color, object: nil, userInfo: info)
|
||||
}
|
||||
}
|
||||
|
||||
class ColorView: NSView {
|
||||
class ParameterView: NSView {
|
||||
private let stackView = NSStackView()
|
||||
internal let colorWell = NSColorWell()
|
||||
internal let label = NSTextField(labelWithString: "Hello")
|
||||
internal let control: NSControl
|
||||
internal let label: NSTextField
|
||||
|
||||
override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
init(frame f: NSRect, control c: NSControl, label: String = "Hello") {
|
||||
control = c
|
||||
self.label = NSTextField(labelWithString: label)
|
||||
super.init(frame: f)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
convenience init(control c: NSControl) {
|
||||
self.init(frame: NSRect(), control: c)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
commonInit()
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
|
@ -217,9 +258,9 @@ class ColorView: NSView {
|
|||
stackView.alignment = .centerY
|
||||
stackView.distribution = .equalSpacing
|
||||
|
||||
colorWell.translatesAutoresizingMaskIntoConstraints = false
|
||||
colorWell.setContentHuggingPriority(251, for: .horizontal)
|
||||
stackView.addArrangedSubview(colorWell)
|
||||
control.translatesAutoresizingMaskIntoConstraints = false
|
||||
control.setContentHuggingPriority(251, for: .horizontal)
|
||||
stackView.addArrangedSubview(control)
|
||||
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.addArrangedSubview(label)
|
||||
|
@ -233,3 +274,31 @@ class ColorView: NSView {
|
|||
])
|
||||
}
|
||||
}
|
||||
|
||||
class ColorView: ParameterView {
|
||||
var colorWell: NSColorWell {
|
||||
return control as! NSColorWell
|
||||
}
|
||||
|
||||
init(label: String) {
|
||||
super.init(frame: NSRect(), control: NSColorWell(), label: label)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
class SliderView: ParameterView {
|
||||
var slider: NSSlider {
|
||||
return control as! NSSlider
|
||||
}
|
||||
|
||||
init(label: String) {
|
||||
super.init(frame: NSRect(), control: NSSlider(), label: label)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,8 +64,8 @@ passthroughVertexShader(uint vid [[vertex_id]],
|
|||
float sampleAtPoint(float2, constant Ball*, int);
|
||||
|
||||
// Color samplers
|
||||
float4 singleColor(float, float, float4);
|
||||
float4 gradient2(float, float, float, float4, float4);
|
||||
float4 singleColor(float, float, float, float4);
|
||||
float4 gradient2(float, float, float, float, float4, float4);
|
||||
|
||||
// Helpers
|
||||
float mapValueFromRangeOntoRange(float, float, float, float, float);
|
||||
|
@ -76,17 +76,18 @@ sampleToColorShader(RasterizerData in [[stage_in]],
|
|||
constant Parameters& parameters [[buffer(0)]],
|
||||
constant Ball* balls [[buffer(1)]])
|
||||
{
|
||||
const float target = 1.0;
|
||||
const float target = parameters.target;
|
||||
const float feather = parameters.feather;
|
||||
const float sample = sampleAtPoint(in.position.xy, balls, parameters.numberOfBalls);
|
||||
const float blend = in.position.x / parameters.size.x;
|
||||
|
||||
float4 out;
|
||||
switch (parameters.colorStyle) {
|
||||
case SingleColor:
|
||||
out = singleColor(sample, target, parameters.colors[0]);
|
||||
out = singleColor(sample, target, feather, parameters.colors[0]);
|
||||
break;
|
||||
case Gradient2Horizontal:
|
||||
out = gradient2(sample, target, blend, parameters.colors[0], parameters.colors[1]);
|
||||
out = gradient2(sample, target, feather, blend, parameters.colors[0], parameters.colors[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -112,15 +113,17 @@ sampleAtPoint(float2 point,
|
|||
float4
|
||||
singleColor(float sample,
|
||||
float target,
|
||||
float feather,
|
||||
float4 color)
|
||||
{
|
||||
float4 out;
|
||||
if (sample > 1.0) {
|
||||
if (sample > target) {
|
||||
out = color;
|
||||
}
|
||||
|
||||
// Feather the alpha value.
|
||||
const float a = clamp(mapValueFromRangeOntoRange(sample, 0.75 * target, target, 0, 1), 0.0, 1.0);
|
||||
const float mappedAlpha = mapValueFromRangeOntoRange(sample, (1.0 - feather) * target, target, 0, 1);
|
||||
const float a = clamp(mappedAlpha, 0.0, 1.0);
|
||||
out = float4(out.xyz, a);
|
||||
|
||||
return out;
|
||||
|
@ -129,12 +132,13 @@ singleColor(float sample,
|
|||
float4
|
||||
gradient2(float sample,
|
||||
float target,
|
||||
float feather,
|
||||
float normalizedBlend,
|
||||
float4 fromColor,
|
||||
float4 toColor)
|
||||
{
|
||||
float4 blendedColor = averageTwoColors(normalizedBlend, fromColor, toColor);
|
||||
float4 out = singleColor(sample, target, blendedColor);
|
||||
float4 out = singleColor(sample, target, feather, blendedColor);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue