Revision: 75606
          http://sourceforge.net/p/brlcad/code/75606
Author:   starseeker
Date:     2020-04-25 19:11:42 +0000 (Sat, 25 Apr 2020)
Log Message:
-----------
Draw white dots in the image buffer based on click+drag mouse events.  Similar 
requirements to altering the image buffer with a new view rendering in response 
to camera adjustments via mouse movement.

Modified Paths:
--------------
    brlcad/trunk/src/libdm/tcl_img.cpp

Modified: brlcad/trunk/src/libdm/tcl_img.cpp
===================================================================
--- brlcad/trunk/src/libdm/tcl_img.cpp  2020-04-25 15:19:06 UTC (rev 75605)
+++ brlcad/trunk/src/libdm/tcl_img.cpp  2020-04-25 19:11:42 UTC (rev 75606)
@@ -26,6 +26,8 @@
 
 #include <random>
 #include <iostream>
+#include <stdlib.h>
+#include <errno.h>
 
 #include "tcl.h"
 #include "tk.h"
@@ -80,9 +82,64 @@
     return TCL_OK;
 }
 
+// Given an X,Y coordinate in a TkPhoto image and a desired offset in
+// X and Y, return the index value into the pixelPtr array N such that
+// N is the integer value of the R color at that X,Y coordiante, N+1
+// is the G value, N+2 is the B value and N+3 is the Alpha value.
+// If either desired offset is beyond the width and height boundaries,
+// cap the return at the minimum/maximum allowed value.
+static int
+img_xy_index(int width, int height, int x, int y, int dx, int dy)
+{
+    int nx = ((x + dx) > width)  ? width  : ((x + dx) < 0) ? 0 : x + dx;
+    int ny = ((y + dy) > height) ? height : ((y + dy) < 0) ? 0 : y + dy;
+    return (ny * width * 4) + nx * 4;
+}
+
 int
+image_paint_xy(ClientData UNUSED(clientData), Tcl_Interp *interp, int argc, 
char **argv)
+{
+    if (argc != 3) {
+       std::cerr << "Unexpected argc: " << argc << "\n";
+       return TCL_ERROR;
+    }
+
+    // Unpack the coordinates (TODO - check errno)
+    char *p_end;
+    long xcoor = strtol(argv[1], &p_end, 10);
+    long ycoor = strtol(argv[2], &p_end, 10);
+
+    // Look up the internals of the image - we're going to directly manipulate
+    // the values of the image to simulate a display manager or framebuffer
+    // changing the visual via rendering.
+    Tk_PhotoImageBlock dm_data;
+    Tk_PhotoHandle dm_img = Tk_FindPhoto(interp, DM_PHOTO);
+    Tk_PhotoGetImage(dm_img, &dm_data);
+
+
+    for (int i = -2; i < 3; i++) {
+       for (int j = -2; j < 3; j++) {
+           int pindex = img_xy_index(dm_data.width, dm_data.height, xcoor, 
ycoor, i, j);
+           // Set to opaque white
+           dm_data.pixelPtr[pindex] = 255;
+           dm_data.pixelPtr[pindex+1] = 255;
+           dm_data.pixelPtr[pindex+2] = 255;
+           dm_data.pixelPtr[pindex+3] = 255;
+       }
+    }
+
+    // Let Tcl/Tk know the photo data has changed, so it can update the 
visuals accordingly.
+    // TODO - a) is it valid and b) is there a performance reason to specify 
just the changed
+    // region rather than the whole data block?
+    Tk_PhotoPutBlock(interp, dm_img, &dm_data, 0, 0, dm_data.width, 
dm_data.height, TK_PHOTO_COMPOSITE_SET);
+
+    return TCL_OK;
+}
+
+int
 main(int UNUSED(argc), const char *argv[])
 {
+    std::string bind_cmd;
 
     // For now, just use a fixed 512x512 image size
     int wsize = 512;
@@ -166,13 +223,23 @@
     std::string pack_cmd = std::string("pack ") + std::string(DM_LABEL);
     Tcl_Eval(interp, pack_cmd.c_str());
 
+
+    // Register a paint command so we can change the image contents neary the 
cursor position
+    (void)Tcl_CreateCommand(interp, "image_paint", (Tcl_CmdProc 
*)image_paint_xy, NULL, (Tcl_CmdDeleteProc* )NULL);
+    // Establish the Button-1+Motion combination event as the trigger for 
drawing on the image
+    bind_cmd = std::string("bind . <B1-Motion> {image_paint %x %y}");
+    Tcl_Eval(interp, bind_cmd.c_str());
+
+
     // Register an update command so we can change the image contents
     (void)Tcl_CreateCommand(interp, "image_update", (Tcl_CmdProc 
*)image_update_data, (ClientData)&idata, (Tcl_CmdDeleteProc* )NULL);
-
-    // Establish the Button-1 event as the trigger for updating the image 
contents
-    std::string bind_cmd = std::string("bind . <Button-1> \"image_update\"");
+    // Establish the Button-2 and Button-3 event as triggers for updating the 
image contents
+    bind_cmd = std::string("bind . <Button-2> {image_update}");
     Tcl_Eval(interp, bind_cmd.c_str());
+    bind_cmd = std::string("bind . <Button-3> {image_update}");
+    Tcl_Eval(interp, bind_cmd.c_str());
 
+
     // Enter the main applicatio loop - the initial image will appear, and 
Button-1 mouse
     // clicks on the window should generate and display new images
     while (1) {

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to