JSUI-MGraphics patch-a-day

    Nov 02 2011 | 3:02 pm
    For the month of November, I'm going to try to produce and post one new JSUI patch that uses the new MGraphics system. I'm currently working on MGraphics documentation, and thought that people would like a jump-start on this as part of learning this new drawing system.
    The MGraphics system is based on the same coding engine used for C-based coding, so it is high-performance and ultra-capable. I hope that you enjoy these patches.
    As Andrew would say: "Happy Patching!"

    • Nov 02 2011 | 3:04 pm
      Here is the patch for November 1, 2011:
      BasicStrokes shows how to set up the mgraphics system and do basic line drawing - called "paths" drawn with "strokes". This is about the simplest useful patch I could come up with, but it hopefully helps you see how easy it is to create a basic UI.
    • Nov 02 2011 | 3:07 pm
      Here is the patch for November 2, 2011:
      BezStrokes is a bit different: it uses the Bezier curve drawing function to create a simple loop from the top, toward the bottom, then back up to the top. I also use "relative coordinate" mode, and have to calculate the aspect ratio in order to fill the display area. Relative coordinates can be easier to work with for arbitrary object sizes, but you have somewhat less control over the actual draw positions.
    • Nov 02 2011 | 6:24 pm
      Thank you very much Darwin,
      very handy for newbies in js like me.
      Do you know why I can open the JSUI.help patcher from your script while I can "call" it from a brand new [jsui] object? Max windows says "no help file found for jsui_default"
    • Nov 02 2011 | 6:30 pm
      I don't know it works that way, but I've seen something similar. I'm going to let Ben know about it to make sure there is a support ticket for this.
    • Nov 02 2011 | 7:40 pm
      Thanks Darwin
    • Nov 03 2011 | 8:39 pm
      Here is the patch for November 3, 2011.
      This is a simple example of drawing circles within the JSUI space, but uses "relative coordinate" mode so that it automatically scales properly. It also determines the aspect ratio in the paint() routine so that it will scale properly in both patching and presentation mode.
      This isn't "art", but it is something that is a great foundation for shape drawing work.
    • Nov 04 2011 | 2:52 pm
      Here is the patch for November 4, 2011:
      This shows some basic uses of the pattern generation functions within mgraphics. The creation of the pattern (pattern_create_linear and pattern_create_radial) builds a gradient for use during shape fills. In these originating calls, you define the "influence" points - the points on a plane that describe the location of gradient startup. If these points are close together, the edge between segments will be tightly defined; if the points are farther apart, the edge will be more of a gradient.
      Once you define the two points, you have to give each a color (using the add_color_stop_rgba function, which needs an index - either 0 or 1 - followed by an rgba color set) and tell the next drawing routine to use this pattern for drawing. The next time you do a fill() or stroke() call, the routine will use the pattern rather than a single color.
      So, in this case, I create a black background (using a rectangle), build up a color, then have a ball displayed/drawn using a background color. You'll notice that the moving ball shows an unchanging background, since the pattern is defined by absolute location rather than relative (to the object) location. Thus, we perform the sleight-of-hand that makes it look like we have a "porthole" into the background, when in fact we are simply drawing the shape using a pattern.
    • Nov 04 2011 | 4:20 pm
      Olivier, Re: opening the jsui help file, this is intentional, as it allows for the possibility to make a help file for a custom jsui.
      It does mean that opening the jsui default help patcher is a little more difficult, but I think this feature is worth keeping around.
      Thanks, -Ben
    • Nov 04 2011 | 5:30 pm
      Hello Ben,
      Ok , it makes sense.
      What is the process to create and link my custom .help file ?
      thank you.
    • Nov 04 2011 | 5:34 pm
      Hi Olivier,
      You can save a max patcher with the same name as your JSUI js file and use the .maxhelp file extension (an option in the save dialog).
    • Nov 04 2011 | 5:40 pm
      as simple as that :-)
    • Nov 05 2011 | 8:12 pm
      Here is the patch for November 5, 2011:
      I wanted to do something that showed management of line width. I started playing with something, and it ended up like this. I'm not sure that it is that useful for learning line width handling, but it does make a cool little op-art display.
    • Nov 05 2011 | 11:33 pm
      nice series...
      animation even works smoothly when the JSUI object is huge... massive improvement over the max5 version
    • Nov 06 2011 | 11:14 am
      yep !
      looks like [JSUI] will have a second life.
    • Nov 06 2011 | 4:01 pm
      Here is the patch for November 6, 2011:
      I wanted to do something with the mouse, with timers and in non-relative mode. So this is what you get: a cool little drawer that does some cool animation on the tail of the draw. Later this week I'll be doing a patch with a little easier means for persistent drawing, but for the moment you can have a little fun with this.
      One fun part of this is to see what happens when mgraphics tries to draw really short, but really wide, lines. You get funky little stars because minute (1- or 2-pixel) lengths cause significant changes in the drawing function.
    • Nov 06 2011 | 6:23 pm
      Darwin, Sweet patches! A fun and productive daily assignment you've set yourself. Possible typo in the lefthand comment in PingAndPong: should be "radial" instead of "linear"? Wishing you courage and strength to make it to 30 on schedule. So far so good! --Chris
    • Nov 06 2011 | 8:21 pm
      So right - the left side is a radial. Updated the patch to support.
      This is the sort of thing I need to provide grounding to my production. It also forces me to figure out some of the more obscure bits of javascript and mgraphics that I also have to document, so it ends up being a productive effort.
      Thanks for the kind words, and I hope you continue to enjoy the results.
    • Nov 07 2011 | 7:16 pm
      Here is the patch for November 7, 2011:
      Time to write some text. Since I don't have anything particular to say for myself, I'll let the fonts speak for themselves.
      Doing a lot of text printing can be a bit of a processing hog. You can see this by increasing the number of fonts to some Really Large Number. Or change the metro to run really fast. These drawn text lines will start to drag on the system...
      But this is a cool introduction to text drawing, and how you can be a little creative with whatever you have on your system.
    • Nov 08 2011 | 10:57 pm
      Here is the patch for November 8, 2011:
      Fun with fonts, again - this time with a little rotation. Can you really make a flower that says "I am a flower"? Easy enough with Max.
      You'll notice in this Javascript that we call "identity_matrix()" after each rotation. That's because the rotate function rotates the drawing area, and therefore needs to be reset after each path fill. Another option would be to rotate by the same amount for each iteration, but that would require a lot more thinking than simply resetting each time.
    • Nov 09 2011 | 11:30 pm
      Here is the patch for November 9, 2011:
      Sometimes, when you are working with relative coordinates, you have to do a little monkey work in order to deal with transformations (translation, rotation and scaling). In this case, we draw our spiral at the top-left, then let the translation functions to their thing.
      If nothing else, it helps us communicate with Dr. Mesmer.
    • Nov 11 2011 | 12:37 am
      Here is the patch for November 10, 2011:
      Up to now, all of our drawing has occurred in the paint() method, which is called every time that the component needs to refresh itself. This is fine in many cases, but troubling in some cases:
      - If the paint method contains some generative function, you cannot know when the visual is going to be recalculated.
      - If your drawing function does *a lot* of stuff, you can find performance starting to suffer.
      So what to do? This sketch shows how to draw to an alternative MGraphics instance, save that visual as an Image object, then use that image to redraw the component during a refresh. The performance is very high (in this case, drawing 1000 semi-transparent rectangles) because the drawing is only done when you ask the drawing to be redone.
      Very important stuff here. Thanks to JKC for the help with this!
    • Nov 11 2011 | 7:51 am
      Thank you so much for doing this. For me, the timing couldn't be better. I'm working on some ideas for an adaptive touchscreen controller with interface elements to be generated by Max as required, and these example patches are going to be enormously helpful in my work.
      From a lifelong geek and nascent Max patcher, sincerely, thank you.
    • Nov 11 2011 | 8:58 pm
      Thanks, Rymf - I'm having a blast with this!
      Here is the patch for November 11, 2011.
      When you create a surface for drawing (using the separate MGraphics instance we saw last time), you don't have to make an opaque surface - it can be alpha channel reduced, allowing us to make semi-transparent figures that can be reused. In this case, I make a Big Red Square, scale the user space when drawing it, then draw a blue circle over the top. Everything is half-alpha'd, so you get a little see-thru no matter what happens.
    • Nov 11 2011 | 11:26 pm
      Quick Q, is MGraphics only available with Max6? (I plan on upgrading but I have to build a new PC before then). I'll take your answer off the air, thanks!
    • Nov 11 2011 | 11:37 pm
      Yup - it's Max 6-only, but for me it's one of the best things about M6 (along with dictionaries, physics, 64-bit audio and curvy patchcords...). Get that PC built, man!
    • Nov 11 2011 | 11:51 pm
      DDG: I'm so far behind the game! It's embarrassing, I can't wait to get the new box and upgrade to 6. Thanks for the re:
    • Nov 13 2011 | 2:21 am
      Here is the patch for November 12, 2011:
      You'll notice by the name of the patch and javascript that this is a rubber stamping of a single image. But when you watch it run, you'll see that it is not a rubber stamp - it's a scaled, rotated and transformed version of the same star, warped and manipulated on the display area.
      When you look at the code, you'll see what's happening - sorta. Some of the actions of the "stamp" are not obvious when you see the code. We are going to be exploring this over the next few days.
      In the meantime, enjoy!
    • Nov 13 2011 | 8:22 pm
      Here is the patch for November 13, 2011:
      In this patch, we are going to investigate what happens when we use the translate function to change the drawing location within mgraphics. You select different menu options to see what happens when you shift the location around. The last menu entry uses the translate function to draw the oscillator in the middle of the box.
      When you use the translate function, you are moving "user space" around. After drawing/rendering is complete, the drawing is clipped to the display area. So, translate calls in a positive direction move the origin (0,0) to the right and down, while translate calls in a negative direction move the origin up and to the left.
      Working with translate() provides a lot of functionality in placing and altering our draw routines.
    • Nov 15 2011 | 2:02 am
      Here is the patch for November 14, 2011:
      This is an investigation of the scale function. It actually acts the way that you'd expect, but the ability to change both X and Y scaling separately gives you some interesting ways to warp your display. In this example, I use the same box and image, but I also included a line of text so you can see how text paths react to the effort.
    • Nov 16 2011 | 5:03 am
      Here is the patch for November 15, 2011:
      Just like the translate and scale functions, we also need to play with the rotate function. However, unlike the previous investigations, this one shows a bit of funky action. Select the last menu item and adjust the number box. The rectangle and the text rotate cleanly, but the image has some issues...
      Therein lies a limitation of the rotation function - image drawing doesn't really survive the rotation process like you'd hope...
      (Note: There appeared to be a problem with the zip file. I've reuploaded, and it looks OK now.)
    • Nov 17 2011 | 12:28 am
      Here is the patch for November 16, 2011:
      Taking a break from the function exploration, I made a little patch that uses the rel_line_to function to build a bit of piping. There's a bit of extra logic to make sure that we aren't going out of bounds, using the get_current_point function.
    • Nov 18 2011 | 5:45 am
      Here is the patch for November 17, 2011:
      One of the problems with the previous example is that we only get one line width for all segments, and only one color (which we didn't even bother to set). You could change these in the main loop, but you'd be disappointed; since the stroke() is not called until after the loop has drawn all the segments, only the last call will be used for the stroke() function.
      In this updated version, we set the colors and locations (and call stroke) at each iteration. However, we also need to save the last position just before the stroke call. Once stroke is called, the path is lost - and therefore, the "current location" is 0,0. So we find the current location just before the stroke(), use that for the next iteration, and are rewarded with the ability to change the line width and color for each segment.
    • Nov 19 2011 | 1:58 am
      Here is the patch for November 18, 2011:
      Back to playing with transformative function - in this case the most arbitrary of all: the transform() function. The transform function takes six arguments, for which I've given the labels xx, xy, yx, yy, x0 and y0. (Note: These are taken from deep within the Max mgraphics code, but you'll see how they relate to the real world in a second...)
      All of the rotate(), translate() and scale() functions can be built into a single transformation using these size values. The xx and yy values control the x and y scaling. The xy and yx values are the basis of the rotate() function. The x0 and y0 values are offsets as provided by the translate() function. But you can see that presenting this information in a matrix format gives you the ability to play with arbitrary scaling and movement options that would be difficult to do with the normal functions.
      It is also important to note the effect of a transform matrix on the lines that are drawn. If you change the line width to 10 or more inside the code, then do more extensive transforms, the line size is directly affected.
      A great place to learn more about the transform function is to look at the Cairo tutorial about transforms, found at:
      Hopefully, this little tester can help you get on top of the transform function and the transformation matrix. Enjoy!
    • Nov 19 2011 | 4:13 pm
      inspiring. keep it up
    • Nov 20 2011 | 4:50 am
      Here is the patch for November 19, 2011:
      What's the use of knowing about the transform() function without actually having any fun with it? This patch uses the XY and YX segments of the transform to give a seasick, psuedo-3D movement to the drawn rectangles. Pretty basic, but also pretty interesting.
      I make a special note of drawing outside the visible area, and letting the transform expose part of the drawn space that you otherwise wouldn't see. If you are doing crazy animations, remember to draw out stuff that may not initially be visible, but will show up after transformation, translation or rotation.
    • Nov 21 2011 | 12:56 am
      Here is the patch for November 20, 2011:
      So digging into cairographics site, I ran across some information about dealing with the distortion of a warped transform matrix. In this example, I use the save() and restore() functions to reset the transformation before the stroke() call is made, thereby making the lines work better.
      With the toggle box in the patch unchecked, it works identically to yesterday's patch. If you turn on the toggle, though, the drawing routine is changed so that stroke() is not called until we restore the transform to its normal state.
      The save() and restore() functions are perfect for this sort of application: a situation where you alter the environment considerably, but don't want to pay a penalty in graphic output quality. I hope this makes sense, but the (somewhat subtle) visible end result should speak for itself.
    • Nov 21 2011 | 11:39 pm
      Thanks for the tutorial patches. They're very helpful. Are you planning to cover the image_surface messages? I'm making a transition from the lcd objects and would like to understand mgraphics capabilities for handling .jpg and .pict files.
      Thanks, Michael
    • Nov 22 2011 | 2:24 am
      Yup - I'm hoping to do more with image_surfaces in a few days. Keep an eye out!
    • Nov 22 2011 | 2:28 am
      Here is the patch for November 21, 2011:
      This is an example of saving a path and reusing it for alternate versions of the path. The "red" part of the display is what I originally draw, while the black (and warped) images are based on reusing the saved path with a variety of rotations, translations and scalings.
      I just also happen to really like this display...
    • Nov 23 2011 | 1:46 am
      Here is the patch for November 22, 2011:
      By request, here is an example of using images with acceptable rotation. In order to do it, you have to actually create an image background for a surface, then use that as a rectangle fill. A little convoluted, but it allows you to use images in a warped environment. Handy stuff...
    • Nov 23 2011 | 1:07 pm
      Here is the patch for November 23, 2011:
      Continuing the exploration of images, in this one we use the set_source_rgba to determine the alpha (transparancy) that will be used for drawing the image to the display area. This allows use to custom fade the output. Again, notice that we also have to translate the location (rather than just move_to()) in order to get the display to position correctly, and that we save() and restore() to return to the normal display layout.
    • Nov 24 2011 | 3:42 pm
      Here is the patch for November 24, 2011:
      This is a simple one, leaving me some time to eat turkey and watch The World Champion Green Bay Packer do whatever they are going to do. Yeah, I'm one of those pathetic knucklehead football fans...
      I'm in the process of putting together a sprite-equivalent; in order to do so, I needed to find out how transparancy is handled. The good news: if you have an image with built-in transparancy, it just works. In this example, I created a really simple "O" with a transparent middle and built a simple overlay automation. Sure enough - the transparancy is maintained through the image_surface_draw call.
    • Nov 24 2011 | 3:53 pm
      hey darwin, 1124TransDraw, win7/64 max 6.0.1
      im getting
      js: TransDraw.js: Javascript ReferenceError: image_surface_draw is not defined, line 37 js: error calling function paint
      enjoy the game!
    • Nov 25 2011 | 3:46 pm
      That's pretty weird; it's working for me on both Windows(7/64) and Mac. image_surface_draw is baseline mgraphics, so I'm curious that it is the single error you are seeing...!
      I'll touch base with Ben to see if he's got any ideas.
    • Nov 25 2011 | 3:49 pm
      Here is the patch for November 25, 2011:
      After a little turkey coma and basking in a Packers win, I decided to open the door to the push and pop routines. Basically, the push_group() routine pushes a drawing activity onto the drawing stack, and pop_group() pulls it off - creating a pattern-surface as a result. This can be dropped into an image and used over and over.
      In this case, you see that when the system calls the paint() routine, it will reuse the existing image, but if I bang the JSUI object, it will recreate a new image. This is the sort of thing that you will have to do if you choose to reuse a display.
    • Nov 25 2011 | 4:17 pm
      thanks for attention, i suspect a traomatic upgrade attempt of iTunes, which messed quicktime. all installed and working
    • Nov 26 2011 | 4:41 pm
      Here is the patch for November 26, 2011:
      Back home from the Wisconsin trip, and time to put the kids to work. "Here's Photoshop. Please make me a spaceship..."
      This is a very simple implementation of a layered sprite system. It has a GenericSprite object, and a use-specific ship object that augments the GenericSprite with a move function. The result is that bangs move the ship back-and-forth among some trees, properly layered within the other sprites.
      Nothing too mgraphics-specific here, but useful for seeing how to perform some basic sprite-like operations within the JSUI/MGraphics system.
    • Nov 27 2011 | 2:56 pm
      Here is the patch for November 27, 2011:
      Just like working with path and image drawing, you can also transform the user space for pattern creation. Rather than stretching this out over several examples, I just created a simple "Pattern Transform Explorer" for you to see how each of the functions works with a simple linear pattern creation.
    • Nov 28 2011 | 7:14 pm
      Here is the patch for November 28, 2011:
      Sometimes it is more convenient to do your drawing with another program, then use JSUI to do the display. The problem is that scaling can get to be sort of grainy. Not the case if you use the SVG file format for the drawing - and use the svg_render() function to render it into the current user space.
      This patch includes a little SVG I created in Illustrator; I use it within JSUI to create a cool little animation with almost no code.
    • Nov 29 2011 | 5:58 pm
      Here is the patch for November 29, 2011:
      Using the transform(), translate(), rotate() and scale() functions give us the ability to do some complex graphical drawing that would otherwise require altogether too much math to consider. In this one, we use these function to create a tilted three-planet orbit display on a pretty blue background.
      Oh, and we also pipe the output to a Jitter matrix! In order to do this, we use the push_group() and pop_group() functions to create a working area for the drawing, produce an image from the result, then display the output in both the JSUI drawing area and output it as a matrix. The translation (from mgraphics to Jitter matrix) isn't perfect, but it gives us the ability to do a lot with the result.
      EDIT: Garf - Joshua pointed out that I didn't have the interp option set up anywhere in my Jitter stream, which caused the problems with Jitter display. In this updated version, I've simply set the interp option of the jit.pwindow, but you could choose to do that anywhere along the way if you chose...
    • Nov 30 2011 | 7:08 pm
      Here is the patch for November 30, 2011:
      Alas, we hit the end of the road. In this ditty, we do a bit of javascript coding to perform a word-wrap on my heartfelt goodbye. Change the font or the font size and the text should wrap accordingly. This uses the text_measure() function to get the width of a string, then back-pedal if we've gone too far.
      Not the most elegant wordwrap function ever written, but you get the idea.
      I hope you've enjoyed the series, and find the mgraphics system to your liking!
    • Jan 08 2012 | 4:36 pm
      Great tutorials Darwin, very useful for many.
      I took the liberty of adding the text from each post to the relevant patcher example and zipped them all together below. The original .zips of each example are also included.
      So download the attached .zip to get all the examples with Darwin's commentary included in each patch.
      All the best,
    • Jan 09 2012 | 9:17 am
      Thanks John! I was about to download all the .zip files.
    • Jan 17 2012 | 8:48 am
      Thanks, John, for helping out!
    • Sep 21 2012 | 11:26 pm
      Hi Darwin,
      In one of your posts above, you mention using mgraphics.relative_coords = 1;
      I'm wondering if you could tell me how to get a similar functionality with the canvas implementation of jsui.
      In my global code, I try: mycontext.relative_coords = 1; ...to no avail. It does look like it works when I load a patch in pres mode by default, but when I switch back and forth, the context draws in patch mode and then not in pres mode.
      Is there something else I can try? It would make working with canvas contexts more useful!
      Thanks, jml
    • Feb 09 2014 | 5:08 pm
      Hi Darwin, I've found your tutorials and exampled very interesting, but I've not found what I'm searching for. My needs are a way to draw a color pattern with more than two colors, and from the left to the right side from a square (not from the angles of it), and not in a circle way. You can see what I mean from the attached image. The colors are red yellow green and blue... Any idea? best regards. Italo
    • Feb 09 2014 | 5:09 pm
      This attachment comes from this video: http://www.youtube.com/watch?v=wC0-3rZWbMY
    • Feb 10 2014 | 4:54 pm
      You could try something like the attached, which creates gradients for the three colors (R, G, B) and overlays them. Not a perfect match, but better performing than doing pixel manipulation.
      One note about gradients; they don't really seem to deal with relative coordinates at all, so if you are doing gradients, you probably want relative_coords turned off.
    • Feb 10 2014 | 8:04 pm
      Many thanks Darwin!!!!!!
    • Feb 10 2014 | 8:28 pm
      I've change it to have 4 colors...not bad at all!!
      // A simple example of using basic drawing routines to // create a complex crossfade. // // For more significant use, you will probably have to // calculate the drawing field, store it, and use it // as a background for later painting. // // -----------------------------------------------------
      mgraphics.init(); mgraphics.relative_coords = 0; mgraphics.autofill = 0;
      var color_centers = [.1, .38, .7, .9]; var myHeight = 1.; var myWidth = .5;
      function bang() { mgraphics.redraw(); }
      function width(h) { myWidth = h; }
      function paint() { gc();
      var tmp;
      var width = this.box.rect[2] - this.box.rect[0]; var height = this.box.rect[3] - this.box.rect[1]; var aspect = width/height; var amount = width * myWidth;
      var myCenters = [color_centers[0] * width, color_centers[1] * width, color_centers[2] * width, color_centers[3] * width];
      with (mgraphics) { // clear the background set_source_rgb(0., 0., 0.); rectangle(0, 0, width, height); fill();
      // test a red fade tmp = pattern_create_linear(myCenters[0]-amount, 0., myCenters[0]+amount, 0); tmp.add_color_stop_rgba(0.0, 1., 0., 0., 0.); tmp.add_color_stop_rgba(0.5, 1., 0., 0., 1.); tmp.add_color_stop_rgba(1.0, 1., 0., 0., 0.); set_source(tmp); rectangle(myCenters[0]-amount, 0., amount*2, height); fill();
      // test a yellow fade tmp = pattern_create_linear(myCenters[1]-amount, 0., myCenters[1]+amount, 0); tmp.add_color_stop_rgba(0.0, 1., 1., 0., 0.); tmp.add_color_stop_rgba(0.5, 1., 1., 0., 1.); tmp.add_color_stop_rgba(1.0, 1., 1., 0., 0.); set_source(tmp); rectangle(myCenters[1]-amount, 0., amount*2, height); fill();
      // test a green fade tmp = pattern_create_linear(myCenters[2]-amount, 0., myCenters[2]+amount, 0); tmp.add_color_stop_rgba(0.0, 0., 1., 0., 0.); tmp.add_color_stop_rgba(0.5, 0., 1., 0., 1.); tmp.add_color_stop_rgba(1.0, 0., 1., 0., 0.); set_source(tmp); rectangle(myCenters[2]-amount, 0., amount*2, height); fill();
      // test a blue fade tmp = pattern_create_linear(myCenters[3]-amount, 0., myCenters[3]+amount, 0); tmp.add_color_stop_rgba(0.0, 0., 0., 1., 0.); tmp.add_color_stop_rgba(0.5, 0., 0., 1., 1.); tmp.add_color_stop_rgba(1.0, 0., 0., 1., 0.); set_source(tmp); rectangle(myCenters[3]-amount, 0., amount*2, height); fill();
      } }
    • Feb 10 2014 | 8:30 pm
    • Feb 10 2014 | 8:31 pm
      That's what I'm talking about - nice work!
    • Feb 11 2014 | 3:43 am
      Hi Darwin. this is my last variation of your script, I've added the height variable. Last thing to do is to see how I can implement the eq curve from the filtergraph...no idea about that... Italo
    • Jun 05 2014 | 7:49 pm
      Hi Darwin,
      Thanks for the mGraphics examples - they really helped me make the interface to my Massachusetts Geophonic Music project.
      Today i took a look at your text wrap example and it had a wrapping bug. If there was a single word that was too long for a line, the next word would be included on that line too, going off the edge. So i fixed it (i think without adding any new bugs). See doWordWrap() in attached for comments detailing my changes.
      Also added a rounded-rectangle backdrop with adjustable margin and corner radius because eventually i want to use this as a transparent info pop-up in patches for end users.
    • Jun 06 2014 | 3:52 pm
      Awesome feedback and additions - thanks!
    • Jun 09 2014 | 7:04 pm
      hey - I made it better! It's now called atp.popupMessage and included in my abstractions set. Added auto-height fitting of the object box (not just background) to the text, optional speech-bubble-style arrows on any side and an optional close button that hides the object. Colors and arrow shape/size/location are customizable. Here it is attached so you don't have to wade through the bitbucket page if you don't want to.
      cheers, Arvid
      EDIT: code updated - download attachment below not this one
    • Jun 09 2014 | 7:21 pm
      Very cool, Arvid!
    • Jun 09 2014 | 8:06 pm
      Sweet! Nice work Arvid.
    • Jun 09 2014 | 8:14 pm
      Thanks! Just updated the defaults to be more generic and support newlines in message. posting again here and on bitbucket.
      Download "atp.popupMessage2.zip" here. There does not appear to be a way to delete or replace attachments on this forum - ?
    • Sep 08 2014 | 2:39 pm
      Im trying to start with mgraphics in jsui. Im using it to display parameters inside a M4L device. However, everytime I switch to presentation view max crashes. I can't go to presentation mode unless I delete all my jsui objects. Check the attachment for the code. Please help!