# Copy from https://github.com/ongaeshi/p5rb/blob/abde2f8a3ca7b33c76b4b3e9f225bb4a5365548d/docs/lib/p5.rb require 'js' # -------------------------------------------- # Constants # # Copyright: p5.js(https://p5js.org/copyright.html) # The p5.js library is free software; # you can redistribute it and/or modify it under the terms of # the GNU Lesser General Public License as published # by the Free Software Foundation, version 2.1. # -------------------------------------------- _PI = Math::PI # The default, two-dimensional renderer. P2D = 'p2d' # One of the two render modes in p5.js: P2D (default renderer) and WEBGL # Enables 3D render by introducing the third dimension: Z WEBGL = 'webgl' # ENVIRONMENT ARROW = 'default' CROSS = 'crosshair' HAND = 'pointer' MOVE = 'move' TEXT = 'text' WAIT = 'wait' # TRIGONOMETRY # HALF_PI is a mathematical constant with the value # 1.57079632679489661923. It is half the ratio of the # circumference of a circle to its diameter. It is useful in # combination with the trigonometric functions sin() and cos(). HALF_PI = _PI / 2 # PI is a mathematical constant with the value # 3.14159265358979323846. It is the ratio of the circumference # of a circle to its diameter. It is useful in combination with # the trigonometric functions sin() and cos(). PI = _PI # QUARTER_PI is a mathematical constant with the value 0.7853982. # It is one quarter the ratio of the circumference of a circle to # its diameter. It is useful in combination with the trigonometric # functions sin() and cos(). QUARTER_PI = _PI / 4 # TAU is an alias for TWO_PI, a mathematical constant with the # value 6.28318530717958647693. It is twice the ratio of the # circumference of a circle to its diameter. It is useful in # combination with the trigonometric functions sin() and cos(). TAU = _PI * 2 # TWO_PI is a mathematical constant with the value # 6.28318530717958647693. It is twice the ratio of the # circumference of a circle to its diameter. It is useful in # combination with the trigonometric functions sin() and cos(). TWO_PI = _PI * 2 # Constant to be used with the angleMode() function, to set the mode in # which p5.js interprets and calculates angles (either DEGREES or RADIANS). DEGREES = 'degrees' # Constant to be used with the angleMode() function, to set the mode # in which p5.js interprets and calculates angles (either RADIANS or DEGREES). RADIANS = 'radians' DEG_TO_RAD = _PI / 180.0 RAD_TO_DEG = 180.0 / _PI CORNER = 'corner' CORNERS = 'corners' RADIUS = 'radius' RIGHT = 'right' LEFT = 'left' CENTER = 'center' TOP = 'top' BOTTOM = 'bottom' BASELINE = 'alphabetic' POINTS = 0x0000 LINES = 0x0001 LINE_STRIP = 0x0003 LINE_LOOP = 0x0002 TRIANGLES = 0x0004 TRIANGLE_FAN = 0x0006 TRIANGLE_STRIP = 0x0005 QUADS = 'quads' QUAD_STRIP = 'quad_strip' TESS = 'tess' CLOSE = 'close' OPEN = 'open' CHORD = 'chord' PIE = 'pie' PROJECT = 'square' # PEND: careful this is counterintuitive SQUARE = 'butt' ROUND = 'round' BEVEL = 'bevel' MITER = 'miter' # COLOR RGB = 'rgb' # HSB (hue, saturation, brightness) is a type of color model. # You can learn more about it at # HSB. HSB = 'hsb' HSL = 'hsl' # DOM EXTENSION # AUTO allows us to automatically set the width or height of an element (but not both), # based on the current height and width of the element. Only one parameter can # be passed to the size function as AUTO, at a time. AUTO = 'auto' # INPUT ALT = 18 BACKSPACE = 8 CONTROL = 17 DELETE = 46 DOWN_ARROW = 40 ENTER = 13 ESCAPE = 27 LEFT_ARROW = 37 OPTION = 18 RETURN = 13 RIGHT_ARROW = 39 SHIFT = 16 TAB = 9 UP_ARROW = 38 # RENDERING BLEND = 'source-over' REMOVE = 'destination-out' ADD = 'lighter' #ADD: 'add', # #SUBTRACT: 'subtract', # DARKEST = 'darken' LIGHTEST = 'lighten' DIFFERENCE = 'difference' SUBTRACT = 'subtract' EXCLUSION = 'exclusion' MULTIPLY = 'multiply' SCREEN = 'screen' REPLACE = 'copy' OVERLAY = 'overlay' HARD_LIGHT = 'hard-light' SOFT_LIGHT = 'soft-light' DODGE = 'color-dodge' BURN = 'color-burn' # FILTERS THRESHOLD = 'threshold' GRAY = 'gray' OPAQUE = 'opaque' INVERT = 'invert' POSTERIZE = 'posterize' DILATE = 'dilate' ERODE = 'erode' BLUR = 'blur' # TYPOGRAPHY NORMAL = 'normal' ITALIC = 'italic' BOLD = 'bold' BOLDITALIC = 'bold italic' CHAR = 'CHAR' WORD = 'WORD' # TYPOGRAPHY-INTERNAL _DEFAULT_TEXT_FILL = '#000000' _DEFAULT_LEADMULT = 1.25 _CTX_MIDDLE = 'middle' # VERTICES LINEAR = 'linear' QUADRATIC = 'quadratic' BEZIER = 'bezier' CURVE = 'curve' # WEBGL DRAWMODES STROKE = 'stroke' FILL = 'fill' TEXTURE = 'texture' IMMEDIATE = 'immediate' # WEBGL TEXTURE MODE # NORMAL already exists for typography IMAGE = 'image' # WEBGL TEXTURE WRAP AND FILTERING # LINEAR already exists above NEAREST = 'nearest' REPEAT = 'repeat' CLAMP = 'clamp' MIRROR = 'mirror' # DEVICE-ORIENTATION LANDSCAPE = 'landscape' PORTRAIT = 'portrait' # DEFAULTS _DEFAULT_STROKE = '#000000' _DEFAULT_FILL = '#FFFFFF' GRID = 'grid' AXES = 'axes' LABEL = 'label' FALLBACK = 'fallback' CONTAIN = 'contain' COVER = 'cover' # -------------------------------------------- # Library # -------------------------------------------- # JS::Object can call property via function style class JS::Object def method_missing(sym, *args, &block) ret = self[sym] case ret.typeof when "undefined" str = sym.to_s if str[-1] == "=" self[str.chop.to_sym] = args.first return args.first end super when "function" self.call(sym, *args, &block).to_r else ret.to_r end end def respond_to_missing?(sym, include_private) return true if super self[sym].typeof != "undefined" end def to_r case self.typeof when "number" self.to_f when "string" self.to_s else self end end end # Call p5.js global functions $p5 = nil def method_missing(sym, *args, &block) return super unless $p5.respond_to?(:[]) ret = $p5[sym] case ret.typeof when "undefined" # str = sym.to_s # if str[-1] == "=" # $p5[str.chop.to_sym] = args.first # return args.first # end super when "function" $p5.call(sym, *args, &block).to_r else ret.to_r end end # Add new p5() to window.constructors.p5() JS.eval("window.constructors = { p5: (...args) => new p5(...args) };") module P5 Vector = JS.global[:p5][:Vector] module_function def init(query = "main", obj = self) unless query.is_a?(String) query, obj = "main", query end $p5&.remove() $p5 = nil sketch = ->(p5) { $p5 = p5 init_method(obj, :preload) init_method(obj, :setup) init_method(obj, :draw) init_event_method(obj, :mouseMoved) init_event_method(obj, :mouseDragged) init_event_method(obj, :mousePressed) init_event_method(obj, :mouseReleased) init_event_method(obj, :mouseClicked) init_event_method(obj, :doubleClicked) init_event_method(obj, :mouseWheel) init_event_method(obj, :keyPressed) init_event_method(obj, :keyReleased) init_event_method(obj, :keyTyped) } container = JS.global.document.querySelector(query) container.innerHTML = "" JS.global.window.constructors.p5(sketch, container) end def init_method(obj, sym) if obj.respond_to?(sym, true) m = obj.method(sym) $p5[sym] = ->() { m.call() } end end def init_event_method(obj, sym) if obj.respond_to?(sym, true) m = obj.method(sym) if m.parameters.count >= 1 $p5[sym] = ->(e) { m.call(e) } else $p5[sym] = ->(e) { m.call() } end end end end