mirror of
https://github.com/processing/processing4.git
synced 2026-02-11 09:39:19 +01:00
moving things around to merge PDE X
This commit is contained in:
367
java/src/processing/mode/experimental/tweak/ColorControlBox.java
Normal file
367
java/src/processing/mode/experimental/tweak/ColorControlBox.java
Normal file
@@ -0,0 +1,367 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import processing.mode.experimental.TextAreaPainter;
|
||||
|
||||
public class ColorControlBox {
|
||||
|
||||
public boolean visible;
|
||||
|
||||
ArrayList<Handle> handles;
|
||||
ColorMode colorMode;
|
||||
Color color;
|
||||
boolean ilegalColor = false;
|
||||
boolean isBW;
|
||||
boolean isHex;
|
||||
|
||||
String drawContext;
|
||||
|
||||
// interface
|
||||
int x, y, width, height;
|
||||
TextAreaPainter painter;
|
||||
|
||||
public ColorControlBox(String context, ColorMode mode, ArrayList<Handle> handles)
|
||||
{
|
||||
this.drawContext = context;
|
||||
this.colorMode = mode;
|
||||
this.handles = handles;
|
||||
|
||||
// add this box to the handles so they can update this color on change
|
||||
for (Handle h : handles) {
|
||||
h.setColorBox(this);
|
||||
}
|
||||
|
||||
isBW = isGrayScale();
|
||||
isHex = isHexColor();
|
||||
color = getCurrentColor();
|
||||
|
||||
visible = Settings.alwaysShowColorBoxes;
|
||||
}
|
||||
|
||||
public void initInterface(TextAreaPainter textAreaPainter, int x, int y, int w, int h)
|
||||
{
|
||||
this.painter = textAreaPainter;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
public void setPos(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void draw(Graphics2D g2d)
|
||||
{
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
AffineTransform trans = g2d.getTransform();
|
||||
g2d.translate(x, y);
|
||||
|
||||
// draw current color
|
||||
g2d.setColor(color);
|
||||
g2d.fillRoundRect(0, 0, width, height, 5, 5);
|
||||
|
||||
// draw black outline
|
||||
g2d.setStroke(new BasicStroke(1));
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.drawRoundRect(0, 0, width, height, 5, 5);
|
||||
|
||||
if (ilegalColor) {
|
||||
g2d.setColor(Color.RED);
|
||||
g2d.setStroke(new BasicStroke(2));
|
||||
g2d.drawLine(width-3, 3, 3, height-3);
|
||||
}
|
||||
|
||||
g2d.setTransform(trans);
|
||||
}
|
||||
|
||||
public boolean isGrayScale()
|
||||
{
|
||||
if (handles.size() <= 2) {
|
||||
int value = handles.get(0).newValue.intValue();
|
||||
if ((value&0xff000000) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if color is hex or webcolor
|
||||
* @return
|
||||
* true if number is hex or webcolor
|
||||
*/
|
||||
private boolean isHexColor()
|
||||
{
|
||||
if (handles.get(0).type == "hex" || handles.get(0).type == "webcolor") {
|
||||
int value = handles.get(0).value.intValue();
|
||||
if ((value&0xff000000) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Color getCurrentColor()
|
||||
{
|
||||
try {
|
||||
if (handles.size() == 1)
|
||||
{
|
||||
if (isBW) {
|
||||
// treat as color(gray)
|
||||
float gray = handles.get(0).newValue.floatValue();
|
||||
return verifiedGrayColor(gray);
|
||||
}
|
||||
else {
|
||||
// treat as color(argb)
|
||||
int argb = handles.get(0).newValue.intValue();
|
||||
return verifiedHexColor(argb);
|
||||
}
|
||||
}
|
||||
else if (handles.size() == 2)
|
||||
{
|
||||
if (isBW) {
|
||||
// color(gray, alpha)
|
||||
float gray = handles.get(0).newValue.floatValue();
|
||||
return verifiedGrayColor(gray);
|
||||
}
|
||||
else {
|
||||
// treat as color(argb, a)
|
||||
int argb = handles.get(0).newValue.intValue();
|
||||
float a = handles.get(1).newValue.floatValue();
|
||||
return verifiedHexColor(argb, a);
|
||||
}
|
||||
}
|
||||
else if (handles.size() == 3)
|
||||
{
|
||||
// color(v1, v2, v3)
|
||||
float v1 = handles.get(0).newValue.floatValue();
|
||||
float v2 = handles.get(1).newValue.floatValue();
|
||||
float v3 = handles.get(2).newValue.floatValue();
|
||||
|
||||
if (colorMode.modeType == ColorMode.RGB) {
|
||||
return verifiedRGBColor(v1, v2, v3, colorMode.aMax);
|
||||
}
|
||||
else {
|
||||
return verifiedHSBColor(v1, v2, v3, colorMode.aMax);
|
||||
}
|
||||
}
|
||||
else if (handles.size() == 4)
|
||||
{
|
||||
// color(v1, v2, v3, alpha)
|
||||
float v1 = handles.get(0).newValue.floatValue();
|
||||
float v2 = handles.get(1).newValue.floatValue();
|
||||
float v3 = handles.get(2).newValue.floatValue();
|
||||
float a = handles.get(3).newValue.floatValue();
|
||||
|
||||
if (colorMode.modeType == ColorMode.RGB) {
|
||||
return verifiedRGBColor(v1, v2, v3, a);
|
||||
}
|
||||
else {
|
||||
return verifiedHSBColor(v1, v2, v3, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println("error parsing color value: " + e.toString());
|
||||
ilegalColor = true;
|
||||
return Color.WHITE;
|
||||
}
|
||||
|
||||
// couldn't figure out this color, return WHITE color
|
||||
ilegalColor = true;
|
||||
return Color.WHITE;
|
||||
}
|
||||
|
||||
private Color verifiedGrayColor(float gray)
|
||||
{
|
||||
if (gray < 0 || gray > colorMode.v1Max) {
|
||||
return colorError();
|
||||
}
|
||||
|
||||
ilegalColor = false;
|
||||
gray = gray/colorMode.v1Max * 255;
|
||||
return new Color((int)gray, (int)gray, (int)gray, 255);
|
||||
}
|
||||
|
||||
private Color verifiedHexColor(int argb)
|
||||
{
|
||||
int r = (argb>>16)&0xff;
|
||||
int g = (argb>>8)&0xff;
|
||||
int b = (argb&0xff);
|
||||
|
||||
ilegalColor = false;
|
||||
return new Color(r, g, b, 255);
|
||||
}
|
||||
|
||||
private Color verifiedHexColor(int argb, float alpha)
|
||||
{
|
||||
int r = (argb>>16)&0xff;
|
||||
int g = (argb>>8)&0xff;
|
||||
int b = (argb&0xff);
|
||||
|
||||
ilegalColor = false;
|
||||
return new Color(r, g, b, 255);
|
||||
}
|
||||
|
||||
public Color verifiedRGBColor(float r, float g, float b, float a)
|
||||
{
|
||||
if (r < 0 || r > colorMode.v1Max ||
|
||||
g < 0 || g > colorMode.v2Max ||
|
||||
b < 0 || b > colorMode.v3Max) {
|
||||
return colorError();
|
||||
}
|
||||
|
||||
ilegalColor = false;
|
||||
r = r/colorMode.v1Max * 255;
|
||||
g = g/colorMode.v2Max * 255;
|
||||
b = b/colorMode.v3Max * 255;
|
||||
return new Color((int)r, (int)g, (int)b, 255);
|
||||
}
|
||||
|
||||
public Color verifiedHSBColor(float h, float s, float b, float a)
|
||||
{
|
||||
if (h < 0 || h > colorMode.v1Max ||
|
||||
s < 0 || s > colorMode.v2Max ||
|
||||
b < 0 || b > colorMode.v3Max) {
|
||||
return colorError();
|
||||
}
|
||||
|
||||
ilegalColor = false;
|
||||
Color c = Color.getHSBColor(h/colorMode.v1Max, s/colorMode.v2Max, b/colorMode.v3Max);
|
||||
return new Color(c.getRed(), c.getGreen(), c.getBlue(), 255);
|
||||
}
|
||||
|
||||
private Color colorError()
|
||||
{
|
||||
ilegalColor = true;
|
||||
return Color.WHITE;
|
||||
}
|
||||
|
||||
public void colorChanged()
|
||||
{
|
||||
color = getCurrentColor();
|
||||
}
|
||||
|
||||
public int getTabIndex()
|
||||
{
|
||||
return handles.get(0).tabIndex;
|
||||
}
|
||||
|
||||
public int getLine()
|
||||
{
|
||||
return handles.get(0).line;
|
||||
}
|
||||
|
||||
public int getCharIndex()
|
||||
{
|
||||
int lastHandle = handles.size()-1;
|
||||
return handles.get(lastHandle).newEndChar + 2;
|
||||
}
|
||||
|
||||
/* Check if the point is in the box
|
||||
*
|
||||
*/
|
||||
public boolean pick(int mx, int my)
|
||||
{
|
||||
if (!visible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mx>x && mx < x+width && my>y && my<y+height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only show the color box if mouse is on the same line
|
||||
*
|
||||
* return true if there was change
|
||||
*/
|
||||
public boolean setMouseY(int my)
|
||||
{
|
||||
boolean change = false;
|
||||
|
||||
if (my>y && my<y+height) {
|
||||
if (!visible) {
|
||||
change = true;
|
||||
}
|
||||
visible = true;
|
||||
}
|
||||
else {
|
||||
if (visible) {
|
||||
change = true;
|
||||
}
|
||||
visible = false;
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
/* Update the color numbers with the new values that were selected
|
||||
* in the color selector
|
||||
*
|
||||
* hue, saturation and brightness parameters are always 0-255
|
||||
*/
|
||||
public void selectorChanged(int hue, int saturation, int brightness)
|
||||
{
|
||||
if (isBW) {
|
||||
// color(gray) or color(gray, alpha)
|
||||
handles.get(0).setValue((float)hue/255*colorMode.v1Max);
|
||||
}
|
||||
else {
|
||||
if (handles.size() == 1 || handles.size() == 2) {
|
||||
// color(argb)
|
||||
int prevVal = handles.get(0).newValue.intValue();
|
||||
int prevAlpha = (prevVal>>24)&0xff;
|
||||
Color c = Color.getHSBColor((float)hue/255, (float)saturation/255, (float)brightness/255);
|
||||
int newVal = (prevAlpha<<24) | (c.getRed()<<16) | (c.getGreen()<<8) | (c.getBlue());
|
||||
handles.get(0).setValue(newVal);
|
||||
}
|
||||
else if (handles.size() == 3 || handles.size() == 4) {
|
||||
// color(v1, v2, v3) or color(v1, v2, v3, alpha)
|
||||
if (colorMode.modeType == ColorMode.HSB) {
|
||||
// HSB
|
||||
float v1 = (float)hue/255 * colorMode.v1Max;
|
||||
float v2 = (float)saturation/255 * colorMode.v2Max;
|
||||
float v3 = (float)brightness/255 * colorMode.v3Max;
|
||||
handles.get(0).setValue(v1);
|
||||
handles.get(1).setValue(v2);
|
||||
handles.get(2).setValue(v3);
|
||||
}
|
||||
else {
|
||||
// RGB
|
||||
Color c = Color.getHSBColor((float)hue/255, (float)saturation/255, (float)brightness/255);
|
||||
handles.get(0).setValue((float)c.getRed()/255*colorMode.v1Max);
|
||||
handles.get(1).setValue((float)c.getGreen()/255*colorMode.v2Max);
|
||||
handles.get(2).setValue((float)c.getBlue()/255*colorMode.v3Max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update our own color
|
||||
color = getCurrentColor();
|
||||
|
||||
// update code text painter so the user will see the changes
|
||||
painter.updateCodeText();
|
||||
painter.repaint();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return handles.size() + " handles, color mode: " + colorMode.toString();
|
||||
}
|
||||
}
|
||||
97
java/src/processing/mode/experimental/tweak/ColorMode.java
Normal file
97
java/src/processing/mode/experimental/tweak/ColorMode.java
Normal file
@@ -0,0 +1,97 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
public class ColorMode {
|
||||
final static int RGB = 0;
|
||||
final static int HSB = 1;
|
||||
|
||||
float v1Max, v2Max, v3Max, aMax;
|
||||
int modeType;
|
||||
|
||||
boolean unrecognizedMode;
|
||||
String drawContext;
|
||||
|
||||
public ColorMode(String context)
|
||||
{
|
||||
this.drawContext = context;
|
||||
modeType = RGB;
|
||||
v1Max = 255;
|
||||
v2Max = 255;
|
||||
v3Max = 255;
|
||||
aMax = 255;
|
||||
|
||||
unrecognizedMode = false;
|
||||
}
|
||||
|
||||
public ColorMode(String context, int type, float v1, float v2, float v3, float a)
|
||||
{
|
||||
this.drawContext = context;
|
||||
modeType = type;
|
||||
v1Max = v1;
|
||||
v2Max = v2;
|
||||
v3Max = v3;
|
||||
aMax = a;
|
||||
|
||||
unrecognizedMode = false;
|
||||
}
|
||||
|
||||
public static ColorMode fromString(String context, String mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
String[] elements = mode.split(",");
|
||||
|
||||
// determine the type of the color mode
|
||||
int type = RGB;
|
||||
if (elements[0].trim().equals("HSB")) {
|
||||
type = HSB;
|
||||
}
|
||||
|
||||
if (elements.length == 1) {
|
||||
// colorMode in the form of colorMode(type)
|
||||
return new ColorMode(context, type, 255, 255, 255, 255);
|
||||
}
|
||||
else if (elements.length == 2) {
|
||||
// colorMode in the form of colorMode(type, max)
|
||||
float max = Float.parseFloat(elements[1].trim());
|
||||
return new ColorMode(context, type, max, max, max, max);
|
||||
}
|
||||
else if (elements.length == 4) {
|
||||
// colorMode in the form of colorMode(type, max1, max2, max3)
|
||||
float r = Float.parseFloat(elements[1].trim());
|
||||
float g = Float.parseFloat(elements[2].trim());
|
||||
float b = Float.parseFloat(elements[3].trim());
|
||||
return new ColorMode(context, type, r, g, b, 255);
|
||||
}
|
||||
else if (elements.length == 5) {
|
||||
// colorMode in the form of colorMode(type, max1, max2, max3, maxA)
|
||||
float r = Float.parseFloat(elements[1].trim());
|
||||
float g = Float.parseFloat(elements[2].trim());
|
||||
float b = Float.parseFloat(elements[3].trim());
|
||||
float a = Float.parseFloat(elements[4].trim());
|
||||
return new ColorMode(context, type, r, g, b, a);
|
||||
}
|
||||
}
|
||||
catch(Exception e) { }
|
||||
|
||||
/* if we failed to parse this mode (uses variables etc..)
|
||||
* we should still keep it so we'll know there is a mode declaration
|
||||
* and we should mark it as unrecognizable
|
||||
*/
|
||||
ColorMode newMode = new ColorMode(context);
|
||||
newMode.unrecognizedMode = true;
|
||||
return newMode;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String type;
|
||||
if (modeType == RGB) {
|
||||
type = "RGB";
|
||||
}
|
||||
else {
|
||||
type = "HSB";
|
||||
}
|
||||
|
||||
return "ColorMode: " + type + ": (" + v1Max + ", " + v2Max + ", " + v3Max + ", " + aMax + ")";
|
||||
}
|
||||
}
|
||||
31
java/src/processing/mode/experimental/tweak/ColorScheme.java
Normal file
31
java/src/processing/mode/experimental/tweak/ColorScheme.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
public class ColorScheme {
|
||||
private static ColorScheme instance = null;
|
||||
public Color redStrokeColor;
|
||||
public Color progressFillColor;
|
||||
public Color progressEmptyColor;
|
||||
public Color markerColor;
|
||||
public Color whitePaneColor;
|
||||
|
||||
private ColorScheme()
|
||||
{
|
||||
redStrokeColor = new Color(160, 20, 20); // dark red
|
||||
progressEmptyColor = new Color(180, 180, 180, 200);
|
||||
progressFillColor = new Color(0, 0, 0, 200);
|
||||
markerColor = new Color(228, 200, 91, 127);
|
||||
whitePaneColor = new Color(255, 255, 255, 120);
|
||||
}
|
||||
|
||||
public static ColorScheme getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ColorScheme();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
398
java/src/processing/mode/experimental/tweak/ColorSelector.java
Normal file
398
java/src/processing/mode/experimental/tweak/ColorSelector.java
Normal file
@@ -0,0 +1,398 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import processing.core.PApplet;
|
||||
import processing.core.PGraphics;
|
||||
import processing.core.PImage;
|
||||
|
||||
public class ColorSelector {
|
||||
int hue, saturation, brightness;
|
||||
|
||||
public JFrame frame;
|
||||
public ColorControlBox colorBox;
|
||||
ColorSelectorBox selectorBox;
|
||||
ColorSelectorSlider selectorSlider;
|
||||
SelectorTopBar topBar;
|
||||
|
||||
|
||||
public ColorSelector(ColorControlBox colorBox)
|
||||
{
|
||||
this.colorBox = colorBox;
|
||||
createFrame();
|
||||
}
|
||||
|
||||
public void createFrame()
|
||||
{
|
||||
frame = new JFrame();
|
||||
frame.setBackground(Color.BLACK);
|
||||
|
||||
Box box = Box.createHorizontalBox();
|
||||
box.setBackground(Color.BLACK);
|
||||
|
||||
selectorSlider = new ColorSelectorSlider();
|
||||
|
||||
if (!colorBox.isBW) {
|
||||
selectorBox = new ColorSelectorBox();
|
||||
box.add(selectorBox.getCanvas());
|
||||
}
|
||||
|
||||
box.add(Box.createHorizontalGlue());
|
||||
box.add(selectorSlider.getCanvas(), BorderLayout.CENTER);
|
||||
box.add(Box.createHorizontalGlue());
|
||||
|
||||
frame.getContentPane().add(box, BorderLayout.CENTER);
|
||||
frame.pack();
|
||||
frame.setResizable(false);
|
||||
frame.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
|
||||
|
||||
selectorBox.init();
|
||||
selectorSlider.init();
|
||||
}
|
||||
|
||||
public void show(int x, int y)
|
||||
{
|
||||
frame.setLocation(x, y);
|
||||
frame.setVisible(true);
|
||||
frame.repaint();
|
||||
}
|
||||
|
||||
public void hide()
|
||||
{
|
||||
this.colorBox = null;
|
||||
frame.setVisible(false);
|
||||
}
|
||||
|
||||
public void refreshColor()
|
||||
{
|
||||
if (colorBox.ilegalColor) {
|
||||
return;
|
||||
}
|
||||
|
||||
setColor(colorBox.color);
|
||||
}
|
||||
|
||||
public void setColor(Color c)
|
||||
{
|
||||
if (selectorBox != null) {
|
||||
selectorBox.setToColor(c);
|
||||
}
|
||||
selectorSlider.setToColor(c);
|
||||
|
||||
repaintSelector();
|
||||
}
|
||||
|
||||
public void satBrightChanged()
|
||||
{
|
||||
repaintSelector();
|
||||
}
|
||||
|
||||
public void hueChanged()
|
||||
{
|
||||
if (selectorBox != null) {
|
||||
selectorBox.renderBack();
|
||||
}
|
||||
repaintSelector();
|
||||
}
|
||||
|
||||
public void repaintSelector()
|
||||
{
|
||||
if (selectorBox != null) {
|
||||
selectorBox.redraw();
|
||||
}
|
||||
selectorSlider.redraw();
|
||||
}
|
||||
|
||||
/*
|
||||
* PApplets for the interactive color fields
|
||||
*/
|
||||
|
||||
public class ColorSelectorBox extends PApplet {
|
||||
int lastX, lastY;
|
||||
PImage backImg;
|
||||
|
||||
public int sketchWidth() { return 255; }
|
||||
|
||||
public int sketchHeight() { return 255; }
|
||||
|
||||
public void setup() {
|
||||
noLoop();
|
||||
colorMode(HSB, 255, 255, 255);
|
||||
noFill();
|
||||
|
||||
if (!colorBox.ilegalColor) {
|
||||
setToColor(colorBox.color);
|
||||
}
|
||||
|
||||
renderBack();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
image(backImg, 0, 0);
|
||||
|
||||
stroke((lastY<128) ? 0 : 255);
|
||||
|
||||
pushMatrix();
|
||||
translate(lastX, lastY);
|
||||
ellipse(0, 0, 5, 5);
|
||||
line(-8, 0, -6, 0);
|
||||
line(6, 0, 8, 0);
|
||||
line(0, -8, 0, -6);
|
||||
line(0, 6, 0, 8);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
public void renderBack() {
|
||||
PGraphics buf = createGraphics(255, 255);
|
||||
buf.colorMode(HSB, 255, 255, 255);
|
||||
buf.beginDraw();
|
||||
buf.loadPixels();
|
||||
int index=0;
|
||||
for (int j=0; j<255; j++) {
|
||||
for (int i=0; i<255; i++) {
|
||||
buf.pixels[index++] = color(hue, i, 255-j);
|
||||
}
|
||||
}
|
||||
buf.updatePixels();
|
||||
buf.endDraw();
|
||||
|
||||
backImg = buf.get();
|
||||
}
|
||||
|
||||
public void setToColor(Color c) {
|
||||
// set selector color
|
||||
float hsb[] = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
|
||||
saturation = (int)(hsb[1]*255);
|
||||
brightness = (int)(hsb[2]*255);
|
||||
lastX = saturation;
|
||||
lastY = 255 - brightness;
|
||||
}
|
||||
|
||||
public void mousePressed() {
|
||||
if (mouseX < 0 || mouseX > 255 ||
|
||||
mouseY < 0 || mouseY > 255) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastX = mouseX;
|
||||
lastY = mouseY;
|
||||
updateColor();
|
||||
}
|
||||
|
||||
public void mouseDragged() {
|
||||
if (mouseX < 0 || mouseX > 255 ||
|
||||
mouseY < 0 || mouseY > 255) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastX = mouseX;
|
||||
lastY = mouseY;
|
||||
updateColor();
|
||||
}
|
||||
|
||||
public void updateColor() {
|
||||
saturation = lastX;
|
||||
brightness = 255 - lastY;
|
||||
|
||||
satBrightChanged();
|
||||
colorBox.selectorChanged(hue, saturation, brightness);
|
||||
}
|
||||
|
||||
/*
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(255, 255);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return new Dimension(255, 255);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(255, 255);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public class ColorSelectorSlider extends PApplet {
|
||||
PImage backImg;
|
||||
int lastY;
|
||||
|
||||
public void setup() {
|
||||
size(30, 255);
|
||||
noLoop();
|
||||
colorMode(HSB, 255, 255, 255);
|
||||
strokeWeight(1);
|
||||
noFill();
|
||||
loadPixels();
|
||||
if (!colorBox.ilegalColor) {
|
||||
setToColor(colorBox.color);
|
||||
}
|
||||
|
||||
// draw the slider background
|
||||
renderBack();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
image(backImg, 0, 0);
|
||||
if (colorBox.isBW) {
|
||||
stroke(lastY<128 ? 0 : 255);
|
||||
}
|
||||
else {
|
||||
stroke(0);
|
||||
}
|
||||
|
||||
pushMatrix();
|
||||
translate(0, lastY);
|
||||
// draw left bracket
|
||||
beginShape();
|
||||
vertex(5, -2);
|
||||
vertex(1, -2);
|
||||
vertex(1, 2);
|
||||
vertex(5, 2);
|
||||
endShape();
|
||||
|
||||
// draw middle lines
|
||||
line(13, 0, 17, 0);
|
||||
line(15, -2, 15, 2);
|
||||
|
||||
// draw right bracket
|
||||
beginShape();
|
||||
vertex(24, -2);
|
||||
vertex(28, -2);
|
||||
vertex(28, 2);
|
||||
vertex(24, 2);
|
||||
endShape();
|
||||
popMatrix();
|
||||
|
||||
if (colorBox.isBW) {
|
||||
stroke(255);
|
||||
rect(0, 0, 29, 254);
|
||||
}
|
||||
else {
|
||||
stroke(0);
|
||||
line(0, 0, 0, 255);
|
||||
line(29, 0, 29, 255);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderBack() {
|
||||
PGraphics buf = createGraphics(30, 255);
|
||||
buf.beginDraw();
|
||||
buf.loadPixels();
|
||||
int index=0;
|
||||
for (int j=0; j<255; j++) {
|
||||
for (int i=0; i<30; i++) {
|
||||
if (colorBox.isBW) {
|
||||
buf.pixels[index++] = color(255-j);
|
||||
}
|
||||
else {
|
||||
buf.pixels[index++] = color(255-j, 255, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.updatePixels();
|
||||
buf.endDraw();
|
||||
|
||||
backImg = buf.get();
|
||||
}
|
||||
|
||||
public void setToColor(Color c)
|
||||
{
|
||||
// set slider position
|
||||
if (colorBox.isBW) {
|
||||
hue = c.getRed();
|
||||
}
|
||||
else {
|
||||
float hsb[] = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
|
||||
hue = (int)(hsb[0]*255);
|
||||
}
|
||||
lastY = 255 - hue;
|
||||
}
|
||||
|
||||
public void mousePressed()
|
||||
{
|
||||
if (mouseX < 0 || mouseX > 30 ||
|
||||
mouseY < 0 || mouseY > 255) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastY = mouseY;
|
||||
updateColor();
|
||||
}
|
||||
|
||||
public void mouseDragged()
|
||||
{
|
||||
if (mouseX < 0 || mouseX > 30 ||
|
||||
mouseY < 0 || mouseY > 255) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastY = mouseY;
|
||||
updateColor();
|
||||
}
|
||||
|
||||
public void updateColor()
|
||||
{
|
||||
hue = 255 - lastY;
|
||||
|
||||
hueChanged();
|
||||
colorBox.selectorChanged(hue, saturation, brightness);
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(30, 255);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return new Dimension(30, 255);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(30, 255);
|
||||
}
|
||||
}
|
||||
|
||||
public class SelectorTopBar extends PApplet
|
||||
{
|
||||
int barWidth;
|
||||
int barHeight;
|
||||
|
||||
public SelectorTopBar(int w)
|
||||
{
|
||||
super();
|
||||
barWidth = w;
|
||||
barHeight = 16;
|
||||
}
|
||||
|
||||
public void setup()
|
||||
{
|
||||
size(barWidth, barHeight);
|
||||
noLoop();
|
||||
}
|
||||
|
||||
public void draw()
|
||||
{
|
||||
background(128);
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(barWidth, barHeight);
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
return new Dimension(barWidth, barHeight);
|
||||
}
|
||||
|
||||
public Dimension getMaximumSize() {
|
||||
return new Dimension(barWidth, barHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
public class HProgressBar {
|
||||
int x, y, size, width;
|
||||
int pos;
|
||||
int lPolyX, rPolyX;
|
||||
Polygon rightPoly, leftPoly;
|
||||
|
||||
public HProgressBar(int size, int width)
|
||||
{
|
||||
this.size = size;
|
||||
this.width = width;
|
||||
x = 0;
|
||||
y = 0;
|
||||
setPos(0);
|
||||
|
||||
|
||||
int xl[] = {0, 0, -(int)(size/1.5)};
|
||||
int yl[] = {-(int)((float)size/3), (int)((float)size/3), 0};
|
||||
leftPoly = new Polygon(xl, yl, 3);
|
||||
int xr[] = {0, (int)(size/1.5), 0};
|
||||
int yr[] = {-(int)((float)size/3), 0, (int)((float)size/3)};
|
||||
rightPoly = new Polygon(xr, yr, 3);
|
||||
}
|
||||
|
||||
public void setPos(int pos)
|
||||
{
|
||||
this.pos = pos;
|
||||
lPolyX = 0;
|
||||
rPolyX = 0;
|
||||
|
||||
if (pos > 0) {
|
||||
rPolyX = pos;
|
||||
}
|
||||
else if (pos < 0) {
|
||||
lPolyX = pos;
|
||||
}
|
||||
}
|
||||
|
||||
public void setWidth(int width)
|
||||
{
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public void draw(Graphics2D g2d)
|
||||
{
|
||||
AffineTransform trans = g2d.getTransform();
|
||||
g2d.translate(x, y);
|
||||
|
||||
// draw white cover on text line
|
||||
g2d.setColor(ColorScheme.getInstance().whitePaneColor);
|
||||
g2d.fillRect(-200+lPolyX, -size, 200-lPolyX-width/2, size+1);
|
||||
g2d.fillRect(width/2, -size, 200+rPolyX, size+1);
|
||||
|
||||
// draw left and right triangles and leading line
|
||||
g2d.setColor(ColorScheme.getInstance().progressFillColor);
|
||||
AffineTransform tmp = g2d.getTransform();
|
||||
g2d.translate(-width/2 - 5 + lPolyX, -size/2);
|
||||
g2d.fillRect(0, -1, -lPolyX, 2);
|
||||
g2d.fillPolygon(leftPoly);
|
||||
g2d.setTransform(tmp);
|
||||
g2d.translate(width/2 + 5 + rPolyX, -size/2);
|
||||
g2d.fillRect(-rPolyX, -1, rPolyX+1, 2);
|
||||
g2d.fillPolygon(rightPoly);
|
||||
g2d.setTransform(tmp);
|
||||
|
||||
g2d.setTransform(trans);
|
||||
}
|
||||
|
||||
}
|
||||
262
java/src/processing/mode/experimental/tweak/Handle.java
Normal file
262
java/src/processing/mode/experimental/tweak/Handle.java
Normal file
@@ -0,0 +1,262 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
|
||||
public class Handle {
|
||||
public String type;
|
||||
public String name;
|
||||
public String strValue;
|
||||
public String strNewValue;
|
||||
public int varIndex;
|
||||
public int startChar;
|
||||
public int endChar;
|
||||
public int newStartChar;
|
||||
public int newEndChar;
|
||||
public int line;
|
||||
int tabIndex;
|
||||
int decimalPlaces; // number of digits after the decimal point
|
||||
float incValue;
|
||||
|
||||
java.lang.Number value, newValue;
|
||||
String strDiff;
|
||||
|
||||
// connect with color control box
|
||||
ColorControlBox colorBox;
|
||||
|
||||
// interface
|
||||
int x, y, width, height;
|
||||
int xCenter, xCurrent, xLast;
|
||||
HProgressBar progBar = null;
|
||||
String textFormat;
|
||||
|
||||
// the client that sends the changes
|
||||
UDPTweakClient tweakClient;
|
||||
|
||||
public Handle(String t, String n, int vi, String v, int ti, int l, int sc,
|
||||
int ec, int dp) {
|
||||
type = t;
|
||||
name = n;
|
||||
varIndex = vi;
|
||||
strValue = v;
|
||||
tabIndex = ti;
|
||||
line = l;
|
||||
startChar = sc;
|
||||
endChar = ec;
|
||||
decimalPlaces = dp;
|
||||
|
||||
incValue = (float) (1 / Math.pow(10, decimalPlaces));
|
||||
|
||||
if (type == "int") {
|
||||
value = newValue = Integer.parseInt(strValue);
|
||||
strNewValue = strValue;
|
||||
textFormat = "%d";
|
||||
} else if (type == "hex") {
|
||||
Long val = Long.parseLong(strValue.substring(2, strValue.length()),
|
||||
16);
|
||||
value = newValue = val.intValue();
|
||||
strNewValue = strValue;
|
||||
textFormat = "0x%x";
|
||||
} else if (type == "webcolor") {
|
||||
Long val = Long.parseLong(strValue.substring(1, strValue.length()),
|
||||
16);
|
||||
val = val | 0xff000000;
|
||||
value = newValue = val.intValue();
|
||||
strNewValue = strValue;
|
||||
textFormat = "#%06x";
|
||||
} else if (type == "float") {
|
||||
value = newValue = Float.parseFloat(strValue);
|
||||
strNewValue = strValue;
|
||||
textFormat = "%.0" + decimalPlaces + "f";
|
||||
}
|
||||
|
||||
newStartChar = startChar;
|
||||
newEndChar = endChar;
|
||||
}
|
||||
|
||||
public void initInterface(int x, int y, int width, int height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
// create drag ball
|
||||
progBar = new HProgressBar(height, width);
|
||||
}
|
||||
|
||||
public void setCenterX(int mx) {
|
||||
xLast = xCurrent = xCenter = mx;
|
||||
}
|
||||
|
||||
public void setCurrentX(int mx) {
|
||||
xLast = xCurrent;
|
||||
xCurrent = mx;
|
||||
|
||||
progBar.setPos(xCurrent - xCenter);
|
||||
|
||||
updateValue();
|
||||
}
|
||||
|
||||
public void resetProgress() {
|
||||
progBar.setPos(0);
|
||||
}
|
||||
|
||||
public void updateValue() {
|
||||
float change = getChange();
|
||||
|
||||
if (type == "int") {
|
||||
if (newValue.intValue() + (int) change > Integer.MAX_VALUE
|
||||
|| newValue.intValue() + (int) change < Integer.MIN_VALUE) {
|
||||
change = 0;
|
||||
return;
|
||||
}
|
||||
setValue(newValue.intValue() + (int) change);
|
||||
} else if (type == "hex") {
|
||||
setValue(newValue.intValue() + (int) change);
|
||||
} else if (type == "webcolor") {
|
||||
setValue(newValue.intValue() + (int) change);
|
||||
} else if (type == "float") {
|
||||
setValue(newValue.floatValue() + change);
|
||||
}
|
||||
|
||||
updateColorBox();
|
||||
}
|
||||
|
||||
public void setValue(Number value) {
|
||||
if (type == "int") {
|
||||
newValue = value.intValue();
|
||||
strNewValue = String.format(Locale.US, textFormat,
|
||||
newValue.intValue());
|
||||
} else if (type == "hex") {
|
||||
newValue = value.intValue();
|
||||
strNewValue = String.format(Locale.US, textFormat,
|
||||
newValue.intValue());
|
||||
} else if (type == "webcolor") {
|
||||
newValue = value.intValue();
|
||||
// keep only RGB
|
||||
int val = (newValue.intValue() & 0xffffff);
|
||||
strNewValue = String.format(Locale.US, textFormat, val);
|
||||
} else if (type == "float") {
|
||||
BigDecimal bd = new BigDecimal(value.floatValue());
|
||||
bd = bd.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP);
|
||||
newValue = bd.floatValue();
|
||||
strNewValue = String.format(Locale.US, textFormat,
|
||||
newValue.floatValue());
|
||||
}
|
||||
|
||||
// send new data to the server in the sketch
|
||||
sendNewValue();
|
||||
}
|
||||
|
||||
public void updateColorBox() {
|
||||
if (colorBox != null) {
|
||||
colorBox.colorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private float getChange() {
|
||||
int pixels = xCurrent - xLast;
|
||||
return pixels * incValue;
|
||||
}
|
||||
|
||||
public void setPos(int nx, int ny) {
|
||||
x = nx;
|
||||
y = ny;
|
||||
}
|
||||
|
||||
public void setWidth(int w) {
|
||||
width = w;
|
||||
|
||||
progBar.setWidth(w);
|
||||
}
|
||||
|
||||
public void draw(Graphics2D g2d, boolean hasFocus) {
|
||||
AffineTransform prevTrans = g2d.getTransform();
|
||||
g2d.translate(x, y);
|
||||
|
||||
// draw underline on the number
|
||||
g2d.setColor(ColorScheme.getInstance().progressFillColor);
|
||||
g2d.drawLine(0, 0, width, 0);
|
||||
|
||||
if (hasFocus) {
|
||||
if (progBar != null) {
|
||||
g2d.translate(width / 2, 2);
|
||||
progBar.draw(g2d);
|
||||
}
|
||||
}
|
||||
|
||||
g2d.setTransform(prevTrans);
|
||||
}
|
||||
|
||||
public boolean pick(int mx, int my) {
|
||||
return pickText(mx, my);
|
||||
}
|
||||
|
||||
public boolean pickText(int mx, int my) {
|
||||
if (mx > x - 2 && mx < x + width + 2 && my > y - height && my < y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean valueChanged() {
|
||||
if (type == "int") {
|
||||
return (value.intValue() != newValue.intValue());
|
||||
} else if (type == "hex") {
|
||||
return (value.intValue() != newValue.intValue());
|
||||
} else if (type == "webcolor") {
|
||||
return (value.intValue() != newValue.intValue());
|
||||
} else {
|
||||
return (value.floatValue() != newValue.floatValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void setColorBox(ColorControlBox box) {
|
||||
colorBox = box;
|
||||
}
|
||||
|
||||
public void setTweakClient(UDPTweakClient client) {
|
||||
tweakClient = client;
|
||||
}
|
||||
|
||||
public void sendNewValue() {
|
||||
int index = varIndex;
|
||||
try {
|
||||
if (type == "int") {
|
||||
tweakClient.sendInt(index, newValue.intValue());
|
||||
} else if (type == "hex") {
|
||||
tweakClient.sendInt(index, newValue.intValue());
|
||||
} else if (type == "webcolor") {
|
||||
tweakClient.sendInt(index, newValue.intValue());
|
||||
} else if (type == "float") {
|
||||
tweakClient.sendFloat(index, newValue.floatValue());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("error sending new value!");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + " " + name + " = " + strValue + " (tab: " + tabIndex
|
||||
+ ", line: " + line + ", start: " + startChar + ", end: "
|
||||
+ endChar + ")";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used for sorting the handles by order of occurrence inside each tab
|
||||
*/
|
||||
class HandleComparator implements Comparator<Handle> {
|
||||
public int compare(Handle handle1, Handle handle2) {
|
||||
int tab = handle1.tabIndex - handle2.tabIndex;
|
||||
if (tab == 0) {
|
||||
return handle1.startChar - handle2.startChar;
|
||||
} else {
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
public class Settings {
|
||||
public static boolean alwaysShowColorBoxes = true;
|
||||
}
|
||||
783
java/src/processing/mode/experimental/tweak/SketchParser.java
Normal file
783
java/src/processing/mode/experimental/tweak/SketchParser.java
Normal file
@@ -0,0 +1,783 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class SketchParser {
|
||||
public List<List<ColorControlBox>> colorBoxes;
|
||||
public List<List<Handle>> allHandles;
|
||||
|
||||
int intVarCount;
|
||||
int floatVarCount;
|
||||
final String varPrefix = "tweakmode";
|
||||
|
||||
String[] codeTabs;
|
||||
boolean requiresComment;
|
||||
ArrayList<ColorMode> colorModes;
|
||||
|
||||
List<List<Range>> scientificNotations;
|
||||
|
||||
|
||||
public SketchParser(String[] codeTabs, boolean requiresComment) {
|
||||
this.codeTabs = codeTabs;
|
||||
this.requiresComment = requiresComment;
|
||||
intVarCount=0;
|
||||
floatVarCount=0;
|
||||
|
||||
scientificNotations = getAllScientificNotations();
|
||||
|
||||
// find, add, and sort all tweakable numbers in the sketch
|
||||
addAllNumbers();
|
||||
|
||||
// handle colors
|
||||
colorModes = findAllColorModes();
|
||||
//colorBoxes = new ArrayList[codeTabs.length];
|
||||
createColorBoxes();
|
||||
createColorBoxesForLights();
|
||||
|
||||
/* If there is more than one color mode per context,
|
||||
* allow only hex and webcolors in this context.
|
||||
* Currently there is no notion of order of execution so we
|
||||
* cannot know which color mode relate to a color.
|
||||
*/
|
||||
handleMultipleColorModes();
|
||||
}
|
||||
|
||||
|
||||
public void addAllNumbers() {
|
||||
//allHandles = new ArrayList[codeTabs.length]; // moved inside addAllDecimalNumbers
|
||||
addAllDecimalNumbers();
|
||||
addAllHexNumbers();
|
||||
addAllWebColorNumbers();
|
||||
//for (int i=0; i<codeTabs.length; i++) {
|
||||
for (List<Handle> handle : allHandles) {
|
||||
//Collections.sort(allHandles[i], new HandleComparator());
|
||||
Collections.sort(handle, new HandleComparator());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of all the numbers in this sketch
|
||||
* @return
|
||||
* list of all numbers in the sketch (excluding hexadecimals)
|
||||
*/
|
||||
private void addAllDecimalNumbers() {
|
||||
allHandles = new ArrayList<>();
|
||||
|
||||
// for every number found:
|
||||
// save its type (int/float), name, value and position in code.
|
||||
|
||||
Pattern p = Pattern.compile("[\\[\\{<>(),\\t\\s\\+\\-\\/\\*^%!|&=?:~]\\d+\\.?\\d*");
|
||||
for (int i = 0; i < codeTabs.length; i++) {
|
||||
//allHandles[i] = new ArrayList<Handle>();
|
||||
List<Handle> handles = new ArrayList<Handle>();
|
||||
allHandles.add(handles);
|
||||
|
||||
String c = codeTabs[i];
|
||||
Matcher m = p.matcher(c);
|
||||
|
||||
while (m.find()) {
|
||||
boolean forceFloat = false;
|
||||
int start = m.start()+1;
|
||||
int end = m.end();
|
||||
|
||||
if (isInComment(start, codeTabs[i])) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requiresComment) {
|
||||
// only add numbers that have the "// tweak" comment in their line
|
||||
if (!lineHasTweakComment(start, c)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore scientific notation (e.g. 1e-6)
|
||||
boolean found = false;
|
||||
for (Range r : scientificNotations.get(i)) {
|
||||
if (r.contains(start)) {
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove any 'f' after the number
|
||||
if (c.charAt(end) == 'f') {
|
||||
forceFloat = true;
|
||||
end++;
|
||||
}
|
||||
|
||||
// if its a negative, include the '-' sign
|
||||
if (c.charAt(start-1) == '-') {
|
||||
if (isNegativeSign(start-2, c)) {
|
||||
start--;
|
||||
}
|
||||
}
|
||||
|
||||
// special case for ignoring (0x...). will be handled later
|
||||
if (c.charAt(m.end()) == 'x' ||
|
||||
c.charAt(m.end()) == 'X') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// special case for ignoring number inside a string ("")
|
||||
if (isInsideString(start, c))
|
||||
continue;
|
||||
|
||||
// beware of the global assignment (bug from 26.07.2013)
|
||||
if (isGlobal(m.start(), c))
|
||||
continue;
|
||||
|
||||
int line = countLines(c.substring(0, start)) - 1; // zero based
|
||||
String value = c.substring(start, end);
|
||||
//value
|
||||
if (value.contains(".") || forceFloat) {
|
||||
// consider this as a float
|
||||
String name = varPrefix + "_float[" + floatVarCount +"]";
|
||||
int decimalDigits = getNumDigitsAfterPoint(value);
|
||||
handles.add(new Handle("float", name, floatVarCount, value, i, line, start, end, decimalDigits));
|
||||
floatVarCount++;
|
||||
} else {
|
||||
// consider this as an int
|
||||
String name = varPrefix + "_int[" + intVarCount +"]";
|
||||
handles.add(new Handle("int", name, intVarCount, value, i, line, start, end, 0));
|
||||
intVarCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all the hexadecimal numbers in the code
|
||||
* @return
|
||||
* list of all hexadecimal numbers in the sketch
|
||||
*/
|
||||
private void addAllHexNumbers()
|
||||
{
|
||||
/* for every number found:
|
||||
* save its type (int/float), name, value and position in code.
|
||||
*/
|
||||
Pattern p = Pattern.compile("[\\[\\{<>(),\\t\\s\\+\\-\\/\\*^%!|&=?:~]0x[A-Fa-f0-9]+");
|
||||
for (int i=0; i<codeTabs.length; i++)
|
||||
{
|
||||
String c = codeTabs[i];
|
||||
Matcher m = p.matcher(c);
|
||||
|
||||
while (m.find())
|
||||
{
|
||||
int start = m.start()+1;
|
||||
int end = m.end();
|
||||
|
||||
if (isInComment(start, codeTabs[i])) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requiresComment) {
|
||||
// only add numbers that have the "// tweak" comment in their line
|
||||
if (!lineHasTweakComment(start, c)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// special case for ignoring number inside a string ("")
|
||||
if (isInsideString(start, c)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// beware of the global assignment (bug from 26.07.2013)
|
||||
if (isGlobal(m.start(), c)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int line = countLines(c.substring(0, start)) - 1; // zero based
|
||||
String value = c.substring(start, end);
|
||||
String name = varPrefix + "_int[" + intVarCount + "]";
|
||||
Handle handle;
|
||||
try {
|
||||
handle = new Handle("hex", name, intVarCount, value, i, line, start, end, 0);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
// don't add this number
|
||||
continue;
|
||||
}
|
||||
allHandles.get(i).add(handle);
|
||||
intVarCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all the webcolors (#) numbers in the code
|
||||
* @return
|
||||
* list of all hexadecimal numbers in the sketch
|
||||
*/
|
||||
private void addAllWebColorNumbers()
|
||||
{
|
||||
Pattern p = Pattern.compile("#[A-Fa-f0-9]{6}");
|
||||
for (int i=0; i<codeTabs.length; i++)
|
||||
{
|
||||
String c = codeTabs[i];
|
||||
Matcher m = p.matcher(c);
|
||||
|
||||
while (m.find())
|
||||
{
|
||||
int start = m.start();
|
||||
int end = m.end();
|
||||
|
||||
if (isInComment(start, codeTabs[i])) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requiresComment) {
|
||||
// only add numbers that have the "// tweak" comment in their line
|
||||
if (!lineHasTweakComment(start, c)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// special case for ignoring number inside a string ("")
|
||||
if (isInsideString(start, c)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// beware of the global assignment (bug from 26.07.2013)
|
||||
if (isGlobal(m.start(), c)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int line = countLines(c.substring(0, start)) - 1; // zero based
|
||||
String value = c.substring(start, end);
|
||||
String name = varPrefix + "_int[" + intVarCount + "]";
|
||||
Handle handle;
|
||||
try {
|
||||
handle = new Handle("webcolor", name, intVarCount, value, i, line, start, end, 0);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
// don't add this number
|
||||
continue;
|
||||
}
|
||||
allHandles.get(i).add(handle);
|
||||
intVarCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<ColorMode> findAllColorModes() {
|
||||
ArrayList<ColorMode> modes = new ArrayList<ColorMode>();
|
||||
|
||||
for (String tab : codeTabs) {
|
||||
int index = -1;
|
||||
// search for a call to colorMode function
|
||||
while ((index = tab.indexOf("colorMode", index+1)) > -1) {
|
||||
// found colorMode at index
|
||||
|
||||
if (isInComment(index, tab)) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
|
||||
index += 9;
|
||||
int parOpen = tab.indexOf('(', index);
|
||||
if (parOpen < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int parClose = tab.indexOf(')', parOpen+1);
|
||||
if (parClose < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// add this mode
|
||||
String modeDesc = tab.substring(parOpen+1, parClose);
|
||||
String context = getObject(index-9, tab);
|
||||
modes.add(ColorMode.fromString(context, modeDesc));
|
||||
}
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
|
||||
private void createColorBoxes() {
|
||||
colorBoxes = new ArrayList<>();
|
||||
// search tab for the functions: 'color', 'fill', 'stroke', 'background', 'tint'
|
||||
Pattern p = Pattern.compile("color\\(|color\\s\\(|fill[\\(\\s]|stroke[\\(\\s]|background[\\(\\s]|tint[\\(\\s]");
|
||||
|
||||
for (int i = 0; i < codeTabs.length; i++) {
|
||||
//colorBoxes[i] = new ArrayList<ColorControlBox>();
|
||||
List<ColorControlBox> colorBox = new ArrayList<ColorControlBox>();
|
||||
colorBoxes.add(colorBox);
|
||||
|
||||
String tab = codeTabs[i];
|
||||
Matcher m = p.matcher(tab);
|
||||
|
||||
while (m.find()) {
|
||||
ArrayList<Handle> colorHandles = new ArrayList<Handle>();
|
||||
|
||||
// look for the '(' and ')' positions
|
||||
int openPar = tab.indexOf("(", m.start());
|
||||
int closePar = tab.indexOf(")", m.end());
|
||||
if (openPar < 0 || closePar < 0) {
|
||||
// ignore this color
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isInComment(m.start(), tab)) {
|
||||
// ignore colors in a comment
|
||||
continue;
|
||||
}
|
||||
|
||||
// look for handles inside the parenthesis
|
||||
for (Handle handle : allHandles.get(i)) {
|
||||
if (handle.startChar > openPar &&
|
||||
handle.endChar <= closePar) {
|
||||
// we have a match
|
||||
colorHandles.add(handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (colorHandles.size() > 0) {
|
||||
/* make sure there is no other stuff between '()' like variables.
|
||||
* substract all handle values from string inside parenthesis and
|
||||
* check there is no garbage left
|
||||
*/
|
||||
String insidePar = tab.substring(openPar+1, closePar);
|
||||
for (Handle h : colorHandles) {
|
||||
insidePar = insidePar.replaceFirst(h.strValue, "");
|
||||
}
|
||||
|
||||
// make sure there is only ' ' and ',' left in the string.
|
||||
boolean garbage = false;
|
||||
for (int j=0; j<insidePar.length(); j++) {
|
||||
if (insidePar.charAt(j) != ' ' && insidePar.charAt(j) != ',') {
|
||||
// don't add this color box because we can not know the
|
||||
// real value of this color
|
||||
garbage = true;
|
||||
}
|
||||
}
|
||||
|
||||
// create a new color box
|
||||
if (!garbage) {
|
||||
// find the context of the color (e.g. this.fill() or <object>.fill())
|
||||
String context = getObject(m.start(), tab);
|
||||
ColorMode cmode = getColorModeForContext(context);
|
||||
|
||||
// not adding color operations for modes we couldn't understand
|
||||
ColorControlBox newCCB = new ColorControlBox(context, cmode, colorHandles);
|
||||
|
||||
if (cmode.unrecognizedMode) {
|
||||
// the color mode is unrecognizable add only if is a hex or webcolor
|
||||
if (newCCB.isHex) {
|
||||
colorBox.add(newCCB);
|
||||
}
|
||||
} else {
|
||||
colorBox.add(newCCB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createColorBoxesForLights() {
|
||||
// search code for light color and material color functions.
|
||||
Pattern p = Pattern.compile("ambientLight[\\(\\s]|directionalLight[\\(\\s]"+
|
||||
"|pointLight[\\(\\s]|spotLight[\\(\\s]|lightSpecular[\\(\\s]"+
|
||||
"|specular[\\(\\s]|ambient[\\(\\s]|emissive[\\(\\s]");
|
||||
|
||||
for (int i=0; i<codeTabs.length; i++) {
|
||||
String tab = codeTabs[i];
|
||||
Matcher m = p.matcher(tab);
|
||||
|
||||
while (m.find()) {
|
||||
ArrayList<Handle> colorHandles = new ArrayList<Handle>();
|
||||
|
||||
// look for the '(' and ')' positions
|
||||
int openPar = tab.indexOf("(", m.start());
|
||||
int closePar = tab.indexOf(")", m.end());
|
||||
if (openPar < 0 || closePar < 0) {
|
||||
// ignore this color
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isInComment(m.start(), tab)) {
|
||||
// ignore colors in a comment
|
||||
continue;
|
||||
}
|
||||
|
||||
// put 'colorParamsEnd' after three parameters inside the parenthesis or at the close
|
||||
int colorParamsEnd = openPar;
|
||||
int commas=3;
|
||||
while (commas-- > 0) {
|
||||
colorParamsEnd=tab.indexOf(",", colorParamsEnd+1);
|
||||
if (colorParamsEnd < 0 ||
|
||||
colorParamsEnd > closePar) {
|
||||
colorParamsEnd = closePar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (Handle handle : allHandles.get(i)) {
|
||||
if (handle.startChar > openPar &&
|
||||
handle.endChar <= colorParamsEnd) {
|
||||
// we have a match
|
||||
colorHandles.add(handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (colorHandles.size() > 0) {
|
||||
/* make sure there is no other stuff between '()' like variables.
|
||||
* substract all handle values from string inside parenthesis and
|
||||
* check there is no garbage left
|
||||
*/
|
||||
String insidePar = tab.substring(openPar+1, colorParamsEnd);
|
||||
for (Handle h : colorHandles) {
|
||||
insidePar = insidePar.replaceFirst(h.strValue, "");
|
||||
}
|
||||
|
||||
// make sure there is only ' ' and ',' left in the string.
|
||||
boolean garbage = false;
|
||||
for (int j=0; j<insidePar.length(); j++) {
|
||||
if (insidePar.charAt(j) != ' ' && insidePar.charAt(j) != ',') {
|
||||
// don't add this color box because we can not know the
|
||||
// real value of this color
|
||||
garbage = true;
|
||||
}
|
||||
}
|
||||
|
||||
// create a new color box
|
||||
if (!garbage) {
|
||||
// find the context of the color (e.g. this.fill() or <object>.fill())
|
||||
String context = getObject(m.start(), tab);
|
||||
ColorMode cmode = getColorModeForContext(context);
|
||||
|
||||
// not adding color operations for modes we couldn't understand
|
||||
ColorControlBox newCCB = new ColorControlBox(context, cmode, colorHandles);
|
||||
|
||||
if (cmode.unrecognizedMode) {
|
||||
// the color mode is unrecognizable add only if is a hex or webcolor
|
||||
if (newCCB.isHex) {
|
||||
colorBoxes.get(i).add(newCCB);
|
||||
}
|
||||
} else {
|
||||
colorBoxes.get(i).add(newCCB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ColorMode getColorModeForContext(String context) {
|
||||
for (ColorMode cm: colorModes) {
|
||||
if (cm.drawContext.equals(context)) {
|
||||
return cm;
|
||||
}
|
||||
}
|
||||
|
||||
// if non found, create the default color mode for this context and return it
|
||||
ColorMode newCM = new ColorMode(context);
|
||||
colorModes.add(newCM);
|
||||
|
||||
return newCM;
|
||||
}
|
||||
|
||||
private void handleMultipleColorModes()
|
||||
{
|
||||
// count how many color modes per context
|
||||
Map<String, Integer> modeCount = new HashMap<String, Integer>();
|
||||
for (ColorMode cm : colorModes)
|
||||
{
|
||||
Integer prev = modeCount.get(cm.drawContext);
|
||||
if (prev == null) {
|
||||
prev=0;
|
||||
}
|
||||
modeCount.put(cm.drawContext, prev+1);
|
||||
}
|
||||
|
||||
// find the contexts that have more than one color mode
|
||||
ArrayList<String> multipleContexts = new ArrayList<String>();
|
||||
Set<String> allContexts = modeCount.keySet();
|
||||
for (String context : allContexts) {
|
||||
if (modeCount.get(context) > 1) {
|
||||
multipleContexts.add(context);
|
||||
}
|
||||
}
|
||||
|
||||
/* keep only hex and web color boxes in color calls
|
||||
* that belong to 'multipleContexts' contexts
|
||||
*/
|
||||
for (int i=0; i<codeTabs.length; i++) {
|
||||
ArrayList<ColorControlBox> toDelete = new ArrayList<ColorControlBox>();
|
||||
for (String context : multipleContexts) {
|
||||
for (ColorControlBox ccb : colorBoxes.get(i)) {
|
||||
if (ccb.drawContext.equals(context) && !ccb.isHex) {
|
||||
toDelete.add(ccb);
|
||||
}
|
||||
}
|
||||
}
|
||||
colorBoxes.get(i).removeAll(toDelete);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<List<Range>> getAllScientificNotations() {
|
||||
//ArrayList<Range> notations[] = new ArrayList[codeTabs.length];
|
||||
List<List<Range>> notations = new ArrayList<>();
|
||||
|
||||
Pattern p = Pattern.compile("[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?[eE][+\\-]?\\d+");
|
||||
//for (int i = 0; i < codeTabs.length; i++) {
|
||||
for (String code : codeTabs) {
|
||||
List<Range> notation = new ArrayList<Range>();
|
||||
//notations[i] = new ArrayList<Range>();
|
||||
//Matcher m = p.matcher(codeTabs[i]);
|
||||
Matcher m = p.matcher(code);
|
||||
while (m.find()) {
|
||||
//notations[i].add(new Range(m.start(), m.end()));
|
||||
notation.add(new Range(m.start(), m.end()));
|
||||
}
|
||||
notations.add(notation);
|
||||
}
|
||||
return notations;
|
||||
}
|
||||
|
||||
|
||||
public static boolean containsTweakComment(String[] codeTabs) {
|
||||
for (String tab : codeTabs) {
|
||||
if (hasTweakComment(tab)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static public boolean lineHasTweakComment(int pos, String code) {
|
||||
int lineEnd = getEndOfLine(pos, code);
|
||||
if (lineEnd < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String line = code.substring(pos, lineEnd);
|
||||
return hasTweakComment(line);
|
||||
}
|
||||
|
||||
|
||||
static private boolean hasTweakComment(String code) {
|
||||
Pattern p = Pattern.compile("\\/\\/.*tweak", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(code);
|
||||
return m.find();
|
||||
}
|
||||
|
||||
|
||||
static private boolean isNegativeSign(int pos, String code) {
|
||||
// go back and look for ,{[(=?+-/*%<>:&|^!~
|
||||
for (int i = pos; i >= 0; i--) {
|
||||
char c = code.charAt(i);
|
||||
if (c != ' ' && c != '\t') {
|
||||
return (c==',' || c=='{' || c=='[' || c=='(' ||
|
||||
c=='=' || c=='?' || c=='+' || c=='-' ||
|
||||
c=='/' || c=='*' || c=='%' || c=='<' ||
|
||||
c=='>' || c==':' || c=='&' || c=='|' ||
|
||||
c=='^' || c=='!' || c=='~');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static private int getNumDigitsAfterPoint(String number) {
|
||||
Pattern p = Pattern.compile("\\.[0-9]+");
|
||||
Matcher m = p.matcher(number);
|
||||
|
||||
if (m.find()) {
|
||||
return m.end() - m.start() - 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static private int countLines(String str) {
|
||||
String[] lines = str.split("\r\n|\n\r|\n|\r");
|
||||
return lines.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Are we inside a string? (TODO: ignore comments in the code)
|
||||
* @param pos
|
||||
* position in the code
|
||||
* @param code
|
||||
* the code
|
||||
* @return
|
||||
*/
|
||||
static private boolean isInsideString(int pos, String code) {
|
||||
int quoteNum = 0; // count '"'
|
||||
|
||||
for (int c = pos; c>=0 && code.charAt(c) != '\n'; c--) {
|
||||
if (code.charAt(c) == '"') {
|
||||
quoteNum++;
|
||||
}
|
||||
}
|
||||
|
||||
if (quoteNum%2 == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a global position?
|
||||
* @param pos position
|
||||
* @param code code
|
||||
* @return
|
||||
* true if the position 'pos' is in global scope in the code 'code'
|
||||
*/
|
||||
static private boolean isGlobal(int pos, String code) {
|
||||
int curlyScope = 0; // count '{-}'
|
||||
|
||||
for (int c=pos; c>=0; c--)
|
||||
{
|
||||
if (code.charAt(c) == '{') {
|
||||
// check if a function or an array assignment
|
||||
for (int cc=c; cc>=0; cc--) {
|
||||
if (code.charAt(cc)==')') {
|
||||
curlyScope++;
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==']') {
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==';') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (code.charAt(c) == '}') {
|
||||
// check if a function or an array assignment
|
||||
for (int cc=c; cc>=0; cc--) {
|
||||
if (code.charAt(cc)==')') {
|
||||
curlyScope--;
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==']') {
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==';') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (curlyScope == 0) {
|
||||
// it is a global position
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
static private boolean isInComment(int pos, String code) {
|
||||
// look for one line comment
|
||||
int lineStart = getStartOfLine(pos, code);
|
||||
if (lineStart < 0) {
|
||||
return false;
|
||||
}
|
||||
if (code.substring(lineStart, pos).indexOf("//") != -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: look for block comments
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static private int getEndOfLine(int pos, String code) {
|
||||
return code.indexOf("\n", pos);
|
||||
}
|
||||
|
||||
|
||||
static private int getStartOfLine(int pos, String code) {
|
||||
while (pos >= 0) {
|
||||
if (code.charAt(pos) == '\n') {
|
||||
return pos+1;
|
||||
}
|
||||
pos--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** returns the object of the function starting at 'pos'
|
||||
*
|
||||
* @param pos
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
static private String getObject(int pos, String code) {
|
||||
boolean readObject = false;
|
||||
String obj = "this";
|
||||
|
||||
while (pos-- >= 0) {
|
||||
if (code.charAt(pos) == '.') {
|
||||
if (!readObject) {
|
||||
obj = "";
|
||||
readObject = true;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (code.charAt(pos) == ' ' || code.charAt(pos) == '\t') {
|
||||
break;
|
||||
}
|
||||
else if (readObject) {
|
||||
obj = code.charAt(pos) + obj;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
static public int getSetupStart(String code) {
|
||||
Pattern p = Pattern.compile("void[\\s\\t\\r\\n]*setup[\\s\\t]*\\(\\)[\\s\\t\\r\\n]*\\{");
|
||||
Matcher m = p.matcher(code);
|
||||
|
||||
if (m.find()) {
|
||||
return m.end();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// private String replaceString(String str, int start, int end, String put) {
|
||||
// return str.substring(0, start) + put + str.substring(end, str.length());
|
||||
// }
|
||||
|
||||
|
||||
class Range {
|
||||
int start;
|
||||
int end;
|
||||
|
||||
public Range(int s, int e) {
|
||||
start = s;
|
||||
end = e;
|
||||
}
|
||||
|
||||
public boolean contains(int v) {
|
||||
return v >= start && v < end;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import processing.app.Base;
|
||||
import processing.app.Editor;
|
||||
import processing.mode.java.JavaToolbar;
|
||||
|
||||
public class TweakToolbar extends JavaToolbar {
|
||||
|
||||
static protected final int RUN = 0;
|
||||
static protected final int STOP = 1;
|
||||
|
||||
static protected final int NEW = 2;
|
||||
static protected final int OPEN = 3;
|
||||
static protected final int SAVE = 4;
|
||||
static protected final int EXPORT = 5;
|
||||
|
||||
public TweakToolbar(Editor editor, Base base) {
|
||||
super(editor, base);
|
||||
}
|
||||
}
|
||||
182
java/src/processing/mode/experimental/tweak/UDPTweakClient.java
Normal file
182
java/src/processing/mode/experimental/tweak/UDPTweakClient.java
Normal file
@@ -0,0 +1,182 @@
|
||||
package galsasson.mode.tweak;
|
||||
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class UDPTweakClient {
|
||||
private DatagramSocket socket;
|
||||
private InetAddress address;
|
||||
private boolean initialized;
|
||||
private int sketchPort;
|
||||
|
||||
static final int VAR_INT = 0;
|
||||
static final int VAR_FLOAT = 1;
|
||||
static final int SHUTDOWN = 0xffffffff;
|
||||
|
||||
public UDPTweakClient(int sketchPort)
|
||||
{
|
||||
this.sketchPort = sketchPort;
|
||||
|
||||
try {
|
||||
socket = new DatagramSocket();
|
||||
// only local sketch is allowed
|
||||
address = InetAddress.getByName("127.0.0.1");
|
||||
initialized = true;
|
||||
}
|
||||
catch (SocketException e) {
|
||||
initialized = false;
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
socket.close();
|
||||
initialized = false;
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
socket.close();
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
{
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// send shutdown to the sketch
|
||||
sendShutdown();
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
public boolean sendInt(int index, int val)
|
||||
{
|
||||
if (!initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] buf = new byte[12];
|
||||
ByteBuffer bb = ByteBuffer.wrap(buf);
|
||||
bb.putInt(0, VAR_INT);
|
||||
bb.putInt(4, index);
|
||||
bb.putInt(8, val);
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, sketchPort);
|
||||
socket.send(packet);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean sendFloat(int index, float val)
|
||||
{
|
||||
if (!initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] buf = new byte[12];
|
||||
ByteBuffer bb = ByteBuffer.wrap(buf);
|
||||
bb.putInt(0, VAR_FLOAT);
|
||||
bb.putInt(4, index);
|
||||
bb.putFloat(8, val);
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, sketchPort);
|
||||
socket.send(packet);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean sendShutdown()
|
||||
{
|
||||
if (!initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] buf = new byte[12];
|
||||
ByteBuffer bb = ByteBuffer.wrap(buf);
|
||||
bb.putInt(0, SHUTDOWN);
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, sketchPort);
|
||||
socket.send(packet);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String getServerCode(int listenPort, boolean hasInts, boolean hasFloats)
|
||||
{
|
||||
String serverCode = ""+
|
||||
"class TweakModeServer extends Thread\n"+
|
||||
"{\n"+
|
||||
" protected DatagramSocket socket = null;\n"+
|
||||
" protected boolean running = true;\n"+
|
||||
" final int INT_VAR = 0;\n"+
|
||||
" final int FLOAT_VAR = 1;\n"+
|
||||
" final int SHUTDOWN = 0xffffffff;\n"+
|
||||
" public TweakModeServer() {\n"+
|
||||
" this(\"TweakModeServer\");\n"+
|
||||
" }\n"+
|
||||
" public TweakModeServer(String name) {\n"+
|
||||
" super(name);\n"+
|
||||
" }\n"+
|
||||
" public void setup()\n"+
|
||||
" {\n"+
|
||||
" try {\n"+
|
||||
" socket = new DatagramSocket("+listenPort+");\n"+
|
||||
" socket.setSoTimeout(250);\n"+
|
||||
" } catch (IOException e) {\n"+
|
||||
" println(\"error: could not create TweakMode server socket\");\n"+
|
||||
" }\n"+
|
||||
" }\n"+
|
||||
" public void run()\n"+
|
||||
" {\n"+
|
||||
" byte[] buf = new byte[256];\n"+
|
||||
" while(running)\n"+
|
||||
" {\n"+
|
||||
" try {\n"+
|
||||
" DatagramPacket packet = new DatagramPacket(buf, buf.length);\n"+
|
||||
" socket.receive(packet);\n"+
|
||||
" ByteBuffer bb = ByteBuffer.wrap(buf);\n"+
|
||||
" int type = bb.getInt(0);\n"+
|
||||
" int index = bb.getInt(4);\n";
|
||||
|
||||
if (hasInts) {
|
||||
serverCode +=
|
||||
" if (type == INT_VAR) {\n"+
|
||||
" int val = bb.getInt(8);\n"+
|
||||
" tweakmode_int[index] = val;\n"+
|
||||
" }\n"+
|
||||
" else ";
|
||||
}
|
||||
if (hasFloats) {
|
||||
serverCode +=
|
||||
" if (type == FLOAT_VAR) {\n"+
|
||||
" float val = bb.getFloat(8);\n"+
|
||||
" tweakmode_float[index] = val;\n"+
|
||||
" }\n"+
|
||||
" else";
|
||||
}
|
||||
serverCode +=
|
||||
" if (type == SHUTDOWN) {\n"+
|
||||
" running = false;\n"+
|
||||
" }\n"+
|
||||
" } catch (SocketTimeoutException e) {\n"+
|
||||
" // nothing to do here just try receiving again\n"+
|
||||
" } catch (Exception e) {\n"+
|
||||
" }\n"+
|
||||
" }\n"+
|
||||
" socket.close();\n"+
|
||||
" }\n"+
|
||||
"}\n\n\n";
|
||||
|
||||
return serverCode;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user