зеркало из https://github.com/xamarin/ios-samples.git
203 строки
6.7 KiB
C#
203 строки
6.7 KiB
C#
#define LINQ
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Foundation;
|
|
using UIKit;
|
|
using CoreGraphics;
|
|
using OpenTK.Platform;
|
|
using OpenGLES;
|
|
using OpenTK.Graphics.ES11;
|
|
|
|
namespace LowLevelGLPaint
|
|
{
|
|
public class Application
|
|
{
|
|
static void Main (string[] args)
|
|
{
|
|
using (var c = Utilities.CreateGraphicsContext(EAGLRenderingAPI.OpenGLES1)) {
|
|
UIApplication.Main (args, null, "AppDelegate");
|
|
}
|
|
}
|
|
}
|
|
|
|
// The name AppDelegate is referenced in the MainWindow.xib file.
|
|
public partial class AppDelegate : UIApplicationDelegate
|
|
{
|
|
|
|
const int PaletteHeight = 30;
|
|
const int PaletteSize = 5;
|
|
const int AccelerometerFrequency = 25;
|
|
const float FilteringFactor = 0.1f;
|
|
const float EraseAccelerationThreshold = 2.0f;
|
|
|
|
static readonly TimeSpan MinEraseInterval = TimeSpan.FromSeconds (0.5);
|
|
|
|
const float LeftMarginPadding = 10.0f;
|
|
const float TopMarginPadding = 10.0f;
|
|
const float RightMarginPadding = 10.0f;
|
|
|
|
double[] myAccelerometer = new double [3];
|
|
SoundEffect erasingSound = new SoundEffect (NSBundle.MainBundle.PathForResource ("Erase", "caf"));
|
|
SoundEffect selectSound = new SoundEffect (NSBundle.MainBundle.PathForResource ("Select", "caf"));
|
|
DateTime lastTime;
|
|
|
|
PaintingView drawingView;
|
|
|
|
// This method is invoked when the application has loaded its UI and its ready to run
|
|
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
|
|
{
|
|
CGRect rect = UIScreen.MainScreen.ApplicationFrame;
|
|
|
|
//Create the OpenGL drawing view and add it to the window
|
|
drawingView = new PaintingView (new CGRect (rect.Location, rect.Size));
|
|
var viewController = new UIViewController ();
|
|
viewController.View = drawingView;
|
|
window.RootViewController = viewController;
|
|
|
|
// Create a segmented control so that the user can choose the brush color.
|
|
var images = new[] {
|
|
UIImage.FromFile ("Images/Red.png"),
|
|
UIImage.FromFile ("Images/Yellow.png"),
|
|
UIImage.FromFile ("Images/Green.png"),
|
|
UIImage.FromFile ("Images/Blue.png"),
|
|
UIImage.FromFile ("Images/Purple.png")
|
|
};
|
|
if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) {
|
|
// we want the original colors, which is not the default iOS7 behaviour, so we need to
|
|
// replace them with ones having the right UIImageRenderingMode
|
|
for (int i = 0; i < images.Length; i++)
|
|
images [i] = images [i].ImageWithRenderingMode (UIImageRenderingMode.AlwaysOriginal);
|
|
}
|
|
var segmentedControl = new UISegmentedControl (images);
|
|
|
|
// Compute a rectangle that is positioned correctly for the segmented control you'll use as a brush color palette
|
|
var frame = new CGRect (rect.X + LeftMarginPadding, rect.Height - PaletteHeight - TopMarginPadding,
|
|
rect.Width - (LeftMarginPadding + RightMarginPadding), PaletteHeight);
|
|
segmentedControl.Frame = frame;
|
|
// When the user chooses a color, the method changeBrushColor: is called.
|
|
segmentedControl.ValueChanged += ChangeBrushColor;
|
|
// Make sure the color of the color complements the black background
|
|
segmentedControl.TintColor = UIColor.DarkGray;
|
|
// Set the third color (index values start at 0)
|
|
segmentedControl.SelectedSegment = 2;
|
|
|
|
// Add the control to the window
|
|
window.AddSubview (segmentedControl);
|
|
// Now that the control is added, you can release it
|
|
// [segmentedControl release];
|
|
|
|
float r, g, b;
|
|
// Define a starting color
|
|
HslToRgb (2.0f / PaletteSize, PaintingView.Saturation, PaintingView.Luminosity, out r, out g, out b);
|
|
// Set the color using OpenGL
|
|
GL.Color4 (r, g, b, PaintingView.BrushOpacity);
|
|
|
|
// Look in the Info.plist file and you'll see the status bar is hidden
|
|
// Set the style to black so it matches the background of the application
|
|
app.SetStatusBarStyle (UIStatusBarStyle.BlackTranslucent, false);
|
|
// Now show the status bar, but animate to the style.
|
|
app.SetStatusBarHidden (false, true);
|
|
|
|
//Configure and enable the accelerometer
|
|
UIAccelerometer.SharedAccelerometer.UpdateInterval = 1.0f / AccelerometerFrequency;
|
|
UIAccelerometer.SharedAccelerometer.Acceleration += OnAccelerated;
|
|
|
|
window.MakeKeyAndVisible ();
|
|
|
|
return true;
|
|
}
|
|
|
|
// This method is required in iPhoneOS 3.0
|
|
public override void OnActivated (UIApplication application)
|
|
{
|
|
}
|
|
|
|
private void OnAccelerated (object sender, UIAccelerometerEventArgs e)
|
|
{
|
|
#if LINQ
|
|
myAccelerometer = new[]{e.Acceleration.X, e.Acceleration.Y, e.Acceleration.Z}
|
|
.Select((v, i) => v * FilteringFactor + myAccelerometer [i] * (1.0f - FilteringFactor))
|
|
.ToArray ();
|
|
#else
|
|
myAccelerometer [0] = e.Acceleration.X * FilteringFactor + myAccelerometer [0] * (1.0 - FilteringFactor);
|
|
myAccelerometer [1] = e.Acceleration.Y * FilteringFactor + myAccelerometer [1] * (1.0 - FilteringFactor);
|
|
myAccelerometer [2] = e.Acceleration.Z * FilteringFactor + myAccelerometer [2] * (1.0 - FilteringFactor);
|
|
#endif
|
|
|
|
// Odd; ObjC always uses myAccelerometer[0], while
|
|
// I'd expect myAccelerometer[0 .. 2]
|
|
var x = e.Acceleration.X - myAccelerometer [0];
|
|
var y = e.Acceleration.Y - myAccelerometer [0];
|
|
var z = e.Acceleration.Z - myAccelerometer [0];
|
|
|
|
var length = Math.Sqrt (x * x + y * y + z * z);
|
|
if (length >= EraseAccelerationThreshold && DateTime.Now > lastTime + MinEraseInterval) {
|
|
erasingSound.Play ();
|
|
drawingView.Erase ();
|
|
lastTime = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
static void HslToRgb (float h, float s, float l, out float r, out float g, out float b)
|
|
{
|
|
// Check for saturation. If there isn't any just return the luminance value for each, which results in gray.
|
|
if (s == 0.0) {
|
|
r = l;
|
|
g = l;
|
|
b = l;
|
|
return;
|
|
}
|
|
|
|
// Test for luminance and compute temporary values based on luminance and saturation
|
|
float temp2;
|
|
if (l < 0.5)
|
|
temp2 = l * (1.0f + s);
|
|
else
|
|
temp2 = l + s - l * s;
|
|
float temp1 = 2.0f * l - temp2;
|
|
|
|
// Compute intermediate values based on hue
|
|
float[] temp = {
|
|
h + 1.0f / 3.0f,
|
|
h,
|
|
h - 1.0f / 3.0f,
|
|
};
|
|
for (int i = 0; i < temp.Length; ++i) {
|
|
if (temp [i] < 0.0f)
|
|
temp [i] += 1.0f;
|
|
if (temp [i] > 1.0f)
|
|
temp [i] -= 1.0f;
|
|
|
|
if (6.0f * temp [i] < 1.0f)
|
|
temp [i] = temp1 + (temp2 - temp1) * 6.0f * temp [i];
|
|
else {
|
|
if (2.0f * temp [i] < 1.0f)
|
|
temp [i] = temp2;
|
|
else {
|
|
if (3.0f * temp [i] < 2.0f)
|
|
temp [i] = temp1 + (temp2 - temp1) * ((2.0f / 3.0f) - temp [i]) * 6.0f;
|
|
else
|
|
temp [i] = temp1;
|
|
}
|
|
}
|
|
}
|
|
r = temp [0];
|
|
g = temp [1];
|
|
b = temp [2];
|
|
}
|
|
|
|
private void ChangeBrushColor (object sender, EventArgs e)
|
|
{
|
|
selectSound.Play ();
|
|
|
|
float r, g, b;
|
|
HslToRgb (((UISegmentedControl) sender).SelectedSegment / (float) PaletteSize,
|
|
PaintingView.Saturation, PaintingView.Luminosity,
|
|
out r, out g, out b);
|
|
GL.Color4 (r, g, b, PaintingView.BrushOpacity);
|
|
}
|
|
}
|
|
}
|
|
|