Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
GPT-4o - BBOX Mouse States - Experiment with a diagram to hint at creation of code.
#1
Star 
Chat GPT-4o is pretty damned good and valuable.

I have the free version, and I want to share something pretty great with you all.

First some back story. I created a diagram using draw.io to help me wrap my head around what I need to do to create a reusable marquee selection style (minus the animation) bounding box that can be used as a crop rectangle. The idea is that I will overlay the bounding box on top of an image and use the coordinates X, Y, and width and height of the box vs. it's relative top left location to the image it's overlaid upon to export a section of the image.

I want this to be very similar to like how GIMP does it with a marquee rectangle selection that can be resized, moved, etc.

I also want to write this once and not have to re-write it constantly over and over, hence my idea "BBOX" object, which I will put into my QB64_GJ_LIB, etc. for reuse.

I will use this in my img2ans program which allows people to render raster images down into ANSI text mode, compatible. See the GitHub repo here for an explanation:
grymmjack/img2ans of this program, and it's purpose. Also a little progress dev-blog exists here in the Discussions section of my repo: this explains some of the progression of what I'm working on.

Right, so that out of the way, here is the diagram (you can get the source for this in draw.io format from my repo here; draw.io diagram for BBOX Mouse States. I also created a video to demonstrate that you can use draw.io Visual Studio Code extension to annotate your project by having it hyperlink straight to your source code (any language) here:


OK, that said, here is the diagram in image format:

[Image: BBOX-state-diag-mouse.png]

Then, here is the prompt that I used to ask GPT to explain it:

I uploaded PNG version of BBOX-state-diag-mouse as you see here, and asked:

Can you read this diagram? And explain what it is?

It said the following
GPT Wrote:Yes, I can read and explain this diagram. This is a state machine diagram for "BBOX Mouse States," which outlines the various states and transitions based on mouse interactions with a bounding box (BBOX) in a graphical user interface (GUI). Here's a breakdown of the components and flow:

### Key Components:
1. **States (in red rounded rectangles)**:
- **DESELECTED**: Default state where the BBOX is not selected.
- **OVER**: State when the mouse is hovering over the BBOX.
- **SELECTED**: State when the BBOX is selected.
- **MOVING**: State when the BBOX is being moved.
- **RESIZING**: State when the BBOX is being resized.
- **ZOOMING**: State when zooming actions are performed.

2. **Operations (in dashed rectangles)**:
- **ZOOM IN**: Action performed when zooming in.
- **ZOOM OUT**: Action performed when zooming out.
- **RESIZE FROM LEFT EDGE, RIGHT EDGE, TOP EDGE, BOTTOM EDGE**: Actions for resizing from respective edges.
- **MOVE UP, DOWN, LEFT, RIGHT**: Actions for moving the BBOX in respective directions.

3. **Conditions (in solid rectangles)**:
- **Mouse Over**: Condition when the mouse is over the BBOX.
- **Mouse Out**: Condition when the mouse moves out of the BBOX.
- **Left Click On BBOX**: Condition when a left-click is performed on the BBOX.
- **Left Click Outside BBOX**: Condition when a left-click is performed outside the BBOX.
- **Drag on Left Edge, Right Edge, Top Edge, Bottom Edge**: Conditions for dragging on respective edges.
- **Drag Not on Edge**: Condition for dragging not on the edge but within the BBOX.
- **Drag Up, Down, Left, Right**: Conditions for dragging in respective directions.
- **Wheel Up, Wheel Down**: Conditions for mouse wheel actions.

### Flow Explanation:

1. **Initial State**:
- The diagram starts from the black dot, indicating the initial state, which leads to the **DESELECTED** state.

2. **Hover and Selection**:
- When the mouse hovers over the BBOX (**Mouse Over**), the state changes to **OVER**.
- From the **OVER** state, a left-click (**Left Click On BBOX**) changes the state to **SELECTED**.
- If the mouse moves out of the BBOX without selecting (**Mouse Out**), the state reverts to **DESELECTED**.

3. **Deselection**:
- From the **SELECTED** state, if a left-click is performed outside the BBOX (**Left Click Outside BBOX**), it transitions back to **DESELECTED**.

4. **Resizing**:
- While in the **SELECTED** state, dragging on the edges of the BBOX (**Drag on Left/Right/Top/Bottom Edge**) transitions to the **RESIZING** state.
- Within the **RESIZING** state, specific actions (resize from respective edges) are performed based on the edge dragged.

5. **Moving**:
- From the **SELECTED** state, dragging within the BBOX but not on the edge (**Drag Not on Edge**) transitions to the **MOVING** state.
- Within the **MOVING** state, dragging in specific directions (up, down, left, right) performs the corresponding move actions.

6. **Zooming**:
- At any point, using the mouse wheel transitions to the **ZOOMING** state.
- In the **ZOOMING** state, specific zoom actions are performed based on the wheel movement (zoom in or zoom out).

This diagram provides a comprehensive view of how mouse interactions transition between different states of a BBOX in a GUI, detailing the conditions and resulting actions for each transition.

This is remarkable and useful, specifically that it intuited:
- Drag Not on Edge: Condition for dragging not on the edge but within the BBOX. (this does not exist in the diagram. it made the intelligent and accurate conclusion.)
- RESIZE FROM LEFT EDGE, RIGHT EDGE, TOP EDGE, BOTTOM EDGE: Actions for resizing from respective edges. (the way it grouped cardinal directions intelligently to summarize and reinforce the meaning.)
- Super helpful is the way it articulated the flow state without me having to beg for it after the fact.

Either i'm an AI whisperer (not likely), my diagram was so good that it was simple to explain (also not really, because I get confused looking at it when I think about how to approach solving for it in code LOL!), or this AI stuff is no joke... Wink

So I figured I'd ask it to write the code too. Using QB64 3.13.1 Wink

---8<---

Continuing from the previous diagram session chat:

Could you please provide a QB64 program to implement this diagram fully? i would like to use this code in a modular way so please create it in a submodule, then also provide an example which uses the included submodule so I can test it. please do this using the latest QB64 Phoenix Edition version which is 3.13.1.

It's response:

GPT Wrote:Sure! Below is a QB64 program that implements the described state machine for BBOX mouse states. The program is divided into a submodule and a main program for testing. This implementation uses the QB64 Phoenix Edition version 3.13.1.

Submodule: bbox_mouse_states_module.bas
First, create a submodule named bbox_mouse_states_module.bas with the following code:
Code: (Select All)

SUB BBOXMouseStates
DIM SHARED mouseX, mouseY, mouseB, mouseOldB, state, dragging, dragStartX, dragStartY, bboxX, bboxY, bboxWidth, bboxHeight

CONST STATE_DESELECTED = 0
CONST STATE_OVER = 1
CONST STATE_SELECTED = 2
CONST STATE_MOVING = 3
CONST STATE_RESIZING = 4
CONST STATE_ZOOMING = 5

' Initialize the bounding box
bboxX = 200
bboxY = 150
bboxWidth = 200
bboxHeight = 150

' Initial state
state = STATE_DESELECTED

DO
_LIMIT 60
CLS
_MOUSEINPUT
mouseX = _MOUSEX
mouseY = _MOUSEY
mouseB = _MOUSEBUTTON(1)

SELECT CASE state
CASE STATE_DESELECTED
IF MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_OVER
END IF
CASE STATE_OVER
IF NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_DESELECTED
ELSEIF mouseB THEN
state = STATE_SELECTED
END IF
CASE STATE_SELECTED
IF NOT mouseB AND NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_DESELECTED
ELSEIF mouseB THEN
dragging = TRUE
dragStartX = mouseX
dragStartY = mouseY
IF MouseOnEdge(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_RESIZING
ELSE
state = STATE_MOVING
END IF
END IF
CASE STATE_MOVING
IF NOT mouseB THEN
state = STATE_SELECTED
dragging = FALSE
ELSE
bboxX = bboxX + (mouseX - dragStartX)
bboxY = bboxY + (mouseY - dragStartY)
dragStartX = mouseX
dragStartY = mouseY
END IF
CASE STATE_RESIZING
IF NOT mouseB THEN
state = STATE_SELECTED
dragging = FALSE
ELSE
' Handle resizing
IF mouseX < bboxX THEN bboxWidth = bboxWidth + (bboxX - mouseX): bboxX = mouseX
IF mouseX > bboxX + bboxWidth THEN bboxWidth = mouseX - bboxX
IF mouseY < bboxY THEN bboxHeight = bboxHeight + (bboxY - mouseY): bboxY = mouseY
IF mouseY > bboxY + bboxHeight THEN bboxHeight = mouseY - bboxY
END IF
END SELECT

' Draw the bounding box
LINE (bboxX, bboxY)-(bboxX + bboxWidth, bboxY + bboxHeight), _RGB32(255, 0, 0), B

' Display current state
SELECT CASE state
CASE STATE_DESELECTED: PRINT "State: DESELECTED"
CASE STATE_OVER: PRINT "State: OVER"
CASE STATE_SELECTED: PRINT "State: SELECTED"
CASE STATE_MOVING: PRINT "State: MOVING"
CASE STATE_RESIZING: PRINT "State: RESIZING"
CASE STATE_ZOOMING: PRINT "State: ZOOMING"
END SELECT

_DISPLAY

mouseOldB = mouseB
LOOP UNTIL INKEY$ = CHR$(27) ' Exit on ESC key
END SUB

FUNCTION MouseOverBBox (mx, my, bx, by, bw, bh)
IF mx >= bx AND mx <= bx + bw AND my >= by AND my <= by + bh THEN
MouseOverBBox = TRUE
ELSE
MouseOverBBox = FALSE
END IF
END FUNCTION

FUNCTION MouseOnEdge (mx, my, bx, by, bw, bh)
IF (mx >= bx AND mx <= bx + 5) OR (mx <= bx + bw AND mx >= bx + bw - 5) OR _
(my >= by AND my <= by + 5) OR (my <= by + bh AND my >= by + bh - 5) THEN
MouseOnEdge = TRUE
ELSE
MouseOnEdge = FALSE
END IF
END FUNCTION

Main Program: main.bas
Next, create the main program named main.bas with the following code to test the submodule:

Code: (Select All)

'$INCLUDE: 'bbox_mouse_states_module.bas'

SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "BBOX Mouse States Demo"

BBOXMouseStates

Instructions to Compile and Run:
Create two files, bbox_mouse_states_module.bas and main.bas, and paste the respective codes into each file.
Open QB64 Phoenix Edition 3.13.1.
Load main.bas into QB64.
Ensure that both files are in the same directory or that the include path is correctly set.
Compile and run main.bas.
This program sets up a window with a bounding box that can be interacted with via mouse actions, implementing the state machine diagram you provided. You can resize, move, and observe state changes as described. Press the ESC key to exit the program.

While it didn't get that I need a input polling loop for mouse events in main, it got me pretty damned far.

I had to share this!

I FOR ONE WELCOME OUR NEW AI OVERLORDS.

The future is bright!

(i have not yet tested the code, I'm just grateful it could simplify my fucking state machine).

with peace and love,
grymmy

P.S.
Also, forgot this but don't want to interrupt the flow, here is a demo of img2ans working:
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#2
The code didn't work as-is.

It assume TRUE and FALSE were constants Smile

I put it in one file to simplify until it worked, it /sorta/ works:

Code: (Select All)

$DEBUG
SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "BBOX Mouse States Demo"

CONST TRUE = -1
CONST FALSE = NOT TRUE

CONST STATE_DESELECTED = 0
CONST STATE_OVER = 1
CONST STATE_SELECTED = 2
CONST STATE_MOVING = 3
CONST STATE_RESIZING = 4
CONST STATE_ZOOMING = 5

REDIM SHARED AS INTEGER _
mouseX, mouseY, _
mouseB, mouseOldB, _
state, dragging, _
dragStartX, dragStartY, _
bboxX, bboxY, _
bboxWidth, bboxHeight

BBOXMouseStates
SYSTEM

SUB BBOXMouseStates
' Initialize the bounding box
bboxX = 200
bboxY = 150
bboxWidth = 200
bboxHeight = 150

' Initial state
state = STATE_DESELECTED

DO
_LIMIT 60
CLS
DO WHILE _MOUSEINPUT:
mouseX = _MOUSEX
mouseY = _MOUSEY
mouseB = _MOUSEBUTTON(1)
LOOP

SELECT CASE state
CASE STATE_DESELECTED
IF MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_OVER
END IF
CASE STATE_OVER
IF NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_DESELECTED
ELSEIF mouseB THEN
state = STATE_SELECTED
END IF
CASE STATE_SELECTED
IF NOT mouseB AND NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_DESELECTED
ELSEIF mouseB THEN
dragging = TRUE
dragStartX = mouseX
dragStartY = mouseY
IF MouseOnEdge(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_RESIZING
ELSE
state = STATE_MOVING
END IF
END IF
CASE STATE_MOVING
IF NOT mouseB THEN
state = STATE_SELECTED
dragging = FALSE
ELSE
bboxX = bboxX + (mouseX - dragStartX)
bboxY = bboxY + (mouseY - dragStartY)
dragStartX = mouseX
dragStartY = mouseY
END IF
CASE STATE_RESIZING
IF NOT mouseB THEN
state = STATE_SELECTED
dragging = FALSE
ELSE
' Handle resizing
IF mouseX < bboxX THEN bboxWidth = bboxWidth + (bboxX - mouseX): bboxX = mouseX
IF mouseX > bboxX + bboxWidth THEN bboxWidth = mouseX - bboxX
IF mouseY < bboxY THEN bboxHeight = bboxHeight + (bboxY - mouseY): bboxY = mouseY
IF mouseY > bboxY + bboxHeight THEN bboxHeight = mouseY - bboxY
END IF
END SELECT

' Draw the bounding box
LINE (bboxX, bboxY)-(bboxX + bboxWidth, bboxY + bboxHeight), _RGB32(255, 0, 0), B

' Display current state
SELECT CASE state
CASE STATE_DESELECTED: PRINT "State: DESELECTED"
CASE STATE_OVER: PRINT "State: OVER"
CASE STATE_SELECTED: PRINT "State: SELECTED"
CASE STATE_MOVING: PRINT "State: MOVING"
CASE STATE_RESIZING: PRINT "State: RESIZING"
CASE STATE_ZOOMING: PRINT "State: ZOOMING"
END SELECT

_DISPLAY

mouseOldB = mouseB
LOOP UNTIL INKEY$ = CHR$(27) ' Exit on ESC key
END SUB

FUNCTION MouseOverBBox (mx, my, bx, by, bw, bh)
IF mx >= bx AND mx <= bx + bw AND my >= by AND my <= by + bh THEN
MouseOverBBox = TRUE
ELSE
MouseOverBBox = FALSE
END IF
END FUNCTION

FUNCTION MouseOnEdge (mx, my, bx, by, bw, bh)
IF (mx >= bx AND mx <= bx + 5) OR (mx <= bx + bw AND mx >= bx + bw - 5) OR _
(my >= by AND my <= by + 5) OR (my <= by + bh AND my >= by + bh - 5) THEN
MouseOnEdge = TRUE
ELSE
MouseOnEdge = FALSE
END IF
END FUNCTION


It actually works, resizing included, but only if I drag outward LOL.

Still, that's pretty bad ass!

Heart
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#3
GPT4o is quite good. It has an uncanny ability to "see", understand, and divine meaning from something. ChatGPT has come a long way. I had a really long CSV at work that I needed cleaning up. I asked it to remove rows that had duplicates in a certain column. There were special characters in the column name that I intentionally omitted. It couldn't find the column at first then, without my intervention, decided to inspect all names and found the one that contained the name I mentioned. Then it tried again. It generated the new CSV really quickly. Then I asked it to instead just spit out that column as a comma-delimited list. And it did that. All by using Python in its own little environment. I am thoroughly impressed. My QB64 GPT isn't that great. It keeps trying to use FreeBASIC or VB code to generate responses. But if I tell it that it is the wrong syntax, it usually will fix it up quite nicely. I've had a few programs made by it that are good right out of the box.
Tread on those who tread on you

Reply
#4
(05-22-2024, 11:31 AM)SpriggsySpriggs Wrote: GPT4o is quite good. It has an uncanny ability to "see", understand, and divine meaning from something. ChatGPT has come a long way. I had a really long CSV at work that I needed cleaning up. I asked it to remove rows that had duplicates in a certain column. There were special characters in the column name that I intentionally omitted. It couldn't find the column at first then, without my intervention, decided to inspect all names and found the one that contained the name I mentioned. Then it tried again. It generated the new CSV really quickly. Then I asked it to instead just spit out that column as a comma-delimited list. And it did that. All by using Python in its own little environment. I am thoroughly impressed. My QB64 GPT isn't that great. It keeps trying to use FreeBASIC or VB code to generate responses. But if I tell it that it is the wrong syntax, it usually will fix it up quite nicely. I've had a few programs made by it that are good right out of the box.

That is awesome. I haven't tried the voice thing yet. I don't really need it I guess Smile

QB64 is like red-head step-child in GitHub too. It always says it is 'FreeBASIC' as the language in a pure QB64 repo.

We should protest for change in GitHub to acknowledge QB64! ... on the steps of the college campus and make an encampment with orange, blue, yellow, and bright cyan tents.
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#5
You apparently can submit a pull request to get your code recognized in GitHub. But you have to do tons of steps.
Tread on those who tread on you

Reply
#6
(05-21-2024, 02:56 AM)grymmjack Wrote: The code didn't work as-is.

It assume TRUE and FALSE were constants Smile

I put it in one file to simplify until it worked, it /sorta/ works:

Code: (Select All)

$DEBUG
SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "BBOX Mouse States Demo"

CONST TRUE = -1
CONST FALSE = NOT TRUE

CONST STATE_DESELECTED = 0
CONST STATE_OVER = 1
CONST STATE_SELECTED = 2
CONST STATE_MOVING = 3
CONST STATE_RESIZING = 4
CONST STATE_ZOOMING = 5

REDIM SHARED AS INTEGER _
    mouseX, mouseY, _
    mouseB, mouseOldB, _
    state, dragging, _
    dragStartX, dragStartY, _
    bboxX, bboxY, _
    bboxWidth, bboxHeight

BBOXMouseStates
SYSTEM

SUB BBOXMouseStates
    ' Initialize the bounding box
    bboxX = 200
    bboxY = 150
    bboxWidth = 200
    bboxHeight = 150

    ' Initial state
    state = STATE_DESELECTED

    DO
        _LIMIT 60
        CLS
        DO WHILE _MOUSEINPUT:
            mouseX = _MOUSEX
            mouseY = _MOUSEY
            mouseB = _MOUSEBUTTON(1)
        LOOP

        SELECT CASE state
            CASE STATE_DESELECTED
                IF MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
                    state = STATE_OVER
                END IF
            CASE STATE_OVER
                IF NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
                    state = STATE_DESELECTED
                ELSEIF mouseB THEN
                    state = STATE_SELECTED
                END IF
            CASE STATE_SELECTED
                IF NOT mouseB AND NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
                    state = STATE_DESELECTED
                ELSEIF mouseB THEN
                    dragging = TRUE
                    dragStartX = mouseX
                    dragStartY = mouseY
                    IF MouseOnEdge(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
                        state = STATE_RESIZING
                    ELSE
                        state = STATE_MOVING
                    END IF
                END IF
            CASE STATE_MOVING
                IF NOT mouseB THEN
                    state = STATE_SELECTED
                    dragging = FALSE
                ELSE
                    bboxX = bboxX + (mouseX - dragStartX)
                    bboxY = bboxY + (mouseY - dragStartY)
                    dragStartX = mouseX
                    dragStartY = mouseY
                END IF
            CASE STATE_RESIZING
                IF NOT mouseB THEN
                    state = STATE_SELECTED
                    dragging = FALSE
                ELSE
                    ' Handle resizing
                    IF mouseX < bboxX THEN bboxWidth = bboxWidth + (bboxX - mouseX): bboxX = mouseX
                    IF mouseX > bboxX + bboxWidth THEN bboxWidth = mouseX - bboxX
                    IF mouseY < bboxY THEN bboxHeight = bboxHeight + (bboxY - mouseY): bboxY = mouseY
                    IF mouseY > bboxY + bboxHeight THEN bboxHeight = mouseY - bboxY
                END IF
        END SELECT

        ' Draw the bounding box
        LINE (bboxX, bboxY)-(bboxX + bboxWidth, bboxY + bboxHeight), _RGB32(255, 0, 0), B

        ' Display current state
        SELECT CASE state
            CASE STATE_DESELECTED: PRINT "State: DESELECTED"
            CASE STATE_OVER: PRINT "State: OVER"
            CASE STATE_SELECTED: PRINT "State: SELECTED"
            CASE STATE_MOVING: PRINT "State: MOVING"
            CASE STATE_RESIZING: PRINT "State: RESIZING"
            CASE STATE_ZOOMING: PRINT "State: ZOOMING"
        END SELECT

        _DISPLAY

        mouseOldB = mouseB
    LOOP UNTIL INKEY$ = CHR$(27) ' Exit on ESC key
END SUB

FUNCTION MouseOverBBox (mx, my, bx, by, bw, bh)
    IF mx >= bx AND mx <= bx + bw AND my >= by AND my <= by + bh THEN
        MouseOverBBox = TRUE
    ELSE
        MouseOverBBox = FALSE
    END IF
END FUNCTION

FUNCTION MouseOnEdge (mx, my, bx, by, bw, bh)
    IF (mx >= bx AND mx <= bx + 5) OR (mx <= bx + bw AND mx >= bx + bw - 5) OR _
      (my >= by AND my <= by + 5) OR (my <= by + bh AND my >= by + bh - 5) THEN
        MouseOnEdge = TRUE
    ELSE
        MouseOnEdge = FALSE
    END IF
END FUNCTION


It actually works, resizing included, but only if I drag outward LOL.

Still, that's pretty bad ass!

Heart
Hi.
Look at this grymmjack .
Code: (Select All)

SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "BBOX Mouse States Demo"

CONST TRUE = -1
CONST FALSE = NOT TRUE

CONST STATE_DESELECTED = 0
CONST STATE_OVER = 1
CONST STATE_SELECTED = 2
CONST STATE_MOVING = 3
CONST STATE_RESIZING = 4
CONST STATE_ZOOMING = 5

CONST MENU_CLOSED = 0
CONST MENU_OPEN = 1

REDIM SHARED AS INTEGER _
    mouseX, mouseY, _
    mouseB, mouseOldB, _
    state, dragging, _
    dragStartX, dragStartY, _
    bboxX, bboxY, _
    bboxWidth, bboxHeight, _
    resizeDirection, _
    topBoxX, topBoxY, _
    topBoxWidth, topBoxHeight, _
    menuState

BBOXMouseStates
SYSTEM

SUB BBOXMouseStates
    ' Αρχικοποίηση του πρώτου κουτιού
    bboxX = 200
    bboxY = 150
    bboxWidth = 200
    bboxHeight = 150

    ' Αρχικοποίηση του δεύτερου κουτιού (πάνω κουτί)
    topBoxX = bboxX
    topBoxY = bboxY - 30 ' Τοποθέτηση πάνω από το πρώτο κουτί
    topBoxWidth = bboxWidth
    topBoxHeight = 30

    ' Αρχική κατάσταση
    state = STATE_DESELECTED
    menuState = MENU_CLOSED

    DO
        _LIMIT 60
        CLS
        DO WHILE _MOUSEINPUT
            mouseX = _MOUSEX
            mouseY = _MOUSEY
            mouseB = _MOUSEBUTTON(1)
        LOOP

        SELECT CASE state
            CASE STATE_DESELECTED
                IF MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
                    state = STATE_OVER
                END IF
            CASE STATE_OVER
                IF NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
                    state = STATE_DESELECTED
                ELSEIF mouseB THEN
                    state = STATE_SELECTED
                END IF
            CASE STATE_SELECTED
                IF NOT mouseB AND NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
                    state = STATE_DESELECTED
                ELSEIF mouseB THEN
                    dragging = TRUE
                    dragStartX = mouseX
                    dragStartY = mouseY
                    resizeDirection = MouseResizeDirection(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight)
                    IF resizeDirection <> 0 THEN
                        state = STATE_RESIZING
                    ELSE
                        state = STATE_MOVING
                    END IF
                END IF
            CASE STATE_MOVING
                IF NOT mouseB THEN
                    state = STATE_SELECTED
                    dragging = FALSE
                ELSE
                    bboxX = bboxX + (mouseX - dragStartX)
                    bboxY = bboxY + (mouseY - dragStartY)
                    dragStartX = mouseX
                    dragStartY = mouseY
                END IF
            CASE STATE_RESIZING
                IF NOT mouseB THEN
                    state = STATE_SELECTED
                    dragging = FALSE
                ELSE
                    ' Διαχείριση αλλαγής μεγέθους
                    IF resizeDirection AND 1 THEN ' Αριστερή πλευρά
                        IF mouseX < bboxX + bboxWidth THEN
                            bboxWidth = bboxWidth + (bboxX - mouseX)
                            bboxX = mouseX
                        END IF
                    END IF
                    IF resizeDirection AND 2 THEN ' Δεξιά πλευρά
                        IF mouseX > bboxX THEN
                            bboxWidth = mouseX - bboxX
                        END IF
                    END IF
                    IF resizeDirection AND 4 THEN ' Άνω πλευρά
                        IF mouseY < bboxY + bboxHeight THEN
                            bboxHeight = bboxHeight + (bboxY - mouseY)
                            bboxY = mouseY
                        END IF
                    END IF
                    IF resizeDirection AND 8 THEN ' Κάτω πλευρά
                        IF mouseY > bboxY THEN
                            bboxHeight = mouseY - bboxY
                        END IF
                    END IF
                END IF
        END SELECT

        ' Ενημέρωση του πάνω κουτιού για να ακολουθεί το πρώτο κουτί
        topBoxX = bboxX
        topBoxY = bboxY - topBoxHeight
        topBoxWidth = bboxWidth

        ' Σχεδίαση του πρώτου κουτιού με πιο χοντρό περίγραμμα
        DrawThickBox bboxX, bboxY, bboxWidth, bboxHeight, 3

        ' Σχεδίαση του πάνω κουτιού με πιο χοντρό περίγραμμα
        DrawThickBox topBoxX, topBoxY, topBoxWidth, topBoxHeight, 3

        ' Σχεδίαση εικονιδίου μενού
        DrawMenuIcon topBoxX, topBoxY

        ' Διαχείριση κατάστασης μενού
        IF mouseB AND MouseOverMenuIcon(mouseX, mouseY, topBoxX, topBoxY) THEN
            IF menuState = MENU_CLOSED THEN
                menuState = MENU_OPEN
            ELSE
                menuState = MENU_CLOSED
            END IF
        END IF

        ' Σχεδίαση μενού αν είναι ανοιχτό
        IF menuState = MENU_OPEN THEN
            DrawMenu topBoxX, topBoxY
        END IF

        ' Σχεδίαση εικονιδίου κλεισίματος
        DrawCloseIcon topBoxX + topBoxWidth - 25, topBoxY

        ' Διαχείριση κλικ επάνω στο εικονίδιο κλεισίματος
        IF mouseB AND MouseOverCloseIcon(mouseX, mouseY, topBoxX + topBoxWidth - 25, topBoxY) THEN
            state = STATE_DESELECTED
            menuState = MENU_CLOSED
            SYSTEM
        END IF

        ' Εμφάνιση της τρέχουσας κατάστασης
        SELECT CASE state
            CASE STATE_DESELECTED: PRINT "Κατάσταση: DESELECTED"
            CASE STATE_OVER: PRINT "Κατάσταση: OVER"
            CASE STATE_SELECTED: PRINT "Κατάσταση: SELECTED"
            CASE STATE_MOVING: PRINT "Κατάσταση: MOVING"
            CASE STATE_RESIZING: PRINT "Κατάσταση: RESIZING"
            CASE STATE_ZOOMING: PRINT "Κατάσταση: ZOOMING"
        END SELECT

        _DISPLAY

        mouseOldB = mouseB
    LOOP UNTIL INKEY$ = CHR$(27) ' Έξοδος με το πλήκτρο ESC
END SUB

FUNCTION MouseOverBBox (mx, my, bx, by, bw, bh)
    IF mx >= bx AND mx <= bx + bw AND my >= by AND my <= by + bh THEN
        MouseOverBBox = TRUE
    ELSE
        MouseOverBBox = FALSE
    END IF
END FUNCTION

FUNCTION MouseResizeDirection (mx, my, bx, by, bw, bh)
    DIM direction AS INTEGER
    direction = 0
    IF mx >= bx AND mx <= bx + 5 THEN direction = direction OR 1 ' Αριστερά
    IF mx >= bx + bw - 5 AND mx <= bx + bw THEN direction = direction OR 2 ' Δεξιά
    IF my >= by AND my <= by + 5 THEN direction = direction OR 4 ' Πάνω
    IF my >= by + bh - 5 AND my <= by + bh THEN direction = direction OR 8 ' Κάτω
    MouseResizeDirection = direction
END FUNCTION

SUB DrawCloseIcon (x, y)
    LINE (x + 5, y + 5)-(x + 25, y + 25), _RGB32(255, 0, 0), B
    LINE (x + 10, y + 10)-(x + 20, y + 20), _RGB32(255, 255, 255)
    LINE (x + 10, y + 20)-(x + 20, y + 10), _RGB32(255, 255, 255)
END SUB

FUNCTION MouseOverCloseIcon (mx, my, x, y)
    IF mx >= x + 5 AND mx <= x + 25 AND my >= y + 5 AND my <= y + 25 THEN
        MouseOverCloseIcon = TRUE
    ELSE
        MouseOverCloseIcon = FALSE
    END IF
END FUNCTION

SUB DrawThickBox (bx, by, bw, bh, thickness)
    FOR i = 0 TO thickness - 1
        LINE (bx - i, by - i)-(bx + bw + i, by + bh - 3 + i), _RGB32(255, 0, 0), B
    NEXT
END SUB

SUB DrawMenuIcon (bw, bh)
    LINE (bw + 5, bh + 5)-(bw + 25, bh + 25), _RGB32(0, 255, 0), B
    LINE (bw + 10, bh + 10)-(bw + 20, bh + 10), _RGB32(255, 255, 255)
    LINE (bw + 10, bh + 15)-(bw + 20, bh + 15), _RGB32(255, 255, 255)
    LINE (bw + 10, bh + 20)-(bw + 20, bh + 20), _RGB32(255, 255, 255)
END SUB

FUNCTION MouseOverMenuIcon (mx, my, bw, bh)
    IF mx >= bw + 5 AND mx <= bw + 25 AND my >= bh + 5 AND my <= bh + 25 THEN
        MouseOverMenuIcon = TRUE
    ELSE
        MouseOverMenuIcon = FALSE
    END IF
END FUNCTION

SUB DrawMenu (bw, bh)
    LINE (bw + 5, bh + 30)-(bw + 105, bh + 130), _RGB32(0, 0, 255), B
    PRINT "Menu item 1"
    PRINT "Menu item 2"
    PRINT "Menu item 3"
END SUB
Reply
#7
+1 nice mods @gaslouk looks good!
b = b + ...
Reply
#8
(05-24-2024, 03:45 AM)gaslouk Wrote: ...

Hey! Thanks! I will try this, I did not get notified of the reply because there was no @ symbol in front of my handle.

Thanks again, excited to see this; will try soon @gaslouk Smile
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#9
@gaslouk

This is great. I didn't think about using a different box to toggle the resize. I will give this approach a go! Thank you for helping me. Smile
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#10
For the benefit of other English speakers, I translated @gaslouk comments to en-us.

Thank you again @gaslouk for your help!

Code: (Select All)

SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "BBOX Mouse States Demo"

CONST TRUE = -1
CONST FALSE = NOT TRUE

CONST STATE_DESELECTED = 0
CONST STATE_OVER = 1
CONST STATE_SELECTED = 2
CONST STATE_MOVING = 3
CONST STATE_RESIZING = 4
CONST STATE_ZOOMING = 5

CONST MENU_CLOSED = 0
CONST MENU_OPEN = 1

REDIM SHARED AS INTEGER _
mouseX, mouseY, _
mouseB, mouseOldB, _
state, dragging, _
dragStartX, dragStartY, _
bboxX, bboxY, _
bboxWidth, bboxHeight, _
resizeDirection, _
topBoxX, topBoxY, _
topBoxWidth, topBoxHeight, _
menuState

BBOXMouseStates
SYSTEM

SUB BBOXMouseStates
' Initializing the first box
bboxX = 200
bboxY = 150
bboxWidth = 200
bboxHeight = 150

' Initialization of the second box (top box)
topBoxX = bboxX
topBoxY = bboxY - 30 ' Placement above the first box
topBoxWidth = bboxWidth
topBoxHeight = 30

' Initial state
state = STATE_DESELECTED
menuState = MENU_CLOSED

DO
_LIMIT 60
CLS
DO WHILE _MOUSEINPUT
mouseX = _MOUSEX
mouseY = _MOUSEY
mouseB = _MOUSEBUTTON(1)
LOOP

SELECT CASE state
CASE STATE_DESELECTED
IF MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_OVER
END IF
CASE STATE_OVER
IF NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_DESELECTED
ELSEIF mouseB THEN
state = STATE_SELECTED
END IF
CASE STATE_SELECTED
IF NOT mouseB AND NOT MouseOverBBox(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight) THEN
state = STATE_DESELECTED
ELSEIF mouseB THEN
dragging = TRUE
dragStartX = mouseX
dragStartY = mouseY
resizeDirection = MouseResizeDirection(mouseX, mouseY, bboxX, bboxY, bboxWidth, bboxHeight)
IF resizeDirection <> 0 THEN
state = STATE_RESIZING
ELSE
state = STATE_MOVING
END IF
END IF
CASE STATE_MOVING
IF NOT mouseB THEN
state = STATE_SELECTED
dragging = FALSE
ELSE
bboxX = bboxX + (mouseX - dragStartX)
bboxY = bboxY + (mouseY - dragStartY)
dragStartX = mouseX
dragStartY = mouseY
END IF
CASE STATE_RESIZING
IF NOT mouseB THEN
state = STATE_SELECTED
dragging = FALSE
ELSE
' Manage resizing
IF resizeDirection AND 1 THEN ' Left side
IF mouseX < bboxX + bboxWidth THEN
bboxWidth = bboxWidth + (bboxX - mouseX)
bboxX = mouseX
END IF
END IF
IF resizeDirection AND 2 THEN ' Right side
IF mouseX > bboxX THEN
bboxWidth = mouseX - bboxX
END IF
END IF
IF resizeDirection AND 4 THEN ' Upper side
IF mouseY < bboxY + bboxHeight THEN
bboxHeight = bboxHeight + (bboxY - mouseY)
bboxY = mouseY
END IF
END IF
IF resizeDirection AND 8 THEN ' Bottom side
IF mouseY > bboxY THEN
bboxHeight = mouseY - bboxY
END IF
END IF
END IF
END SELECT

' Update the top box to follow the first box
topBoxX = bboxX
topBoxY = bboxY - topBoxHeight
topBoxWidth = bboxWidth

' Drawing the first box with a thicker border
DrawThickBox bboxX, bboxY, bboxWidth, bboxHeight, 3

' Top box design with a thicker border
DrawThickBox topBoxX, topBoxY, topBoxWidth, topBoxHeight, 3

' Menu icon design
DrawMenuIcon topBoxX, topBoxY

' Manage menu status
IF mouseB AND MouseOverMenuIcon(mouseX, mouseY, topBoxX, topBoxY) THEN
IF menuState = MENU_CLOSED THEN
menuState = MENU_OPEN
ELSE
menuState = MENU_CLOSED
END IF
END IF

' Menu design if open
IF menuState = MENU_OPEN THEN
DrawMenu topBoxX, topBoxY
END IF

' Close icon design
DrawCloseIcon topBoxX + topBoxWidth - 25, topBoxY

' Manage click on close icon
IF mouseB AND MouseOverCloseIcon(mouseX, mouseY, topBoxX + topBoxWidth - 25, topBoxY) THEN
state = STATE_DESELECTED
menuState = MENU_CLOSED
SYSTEM
END IF

' Show current status
SELECT CASE state
CASE STATE_DESELECTED: PRINT "Situation: DESELECTED"
CASE STATE_OVER: PRINT "Situation: OVER"
CASE STATE_SELECTED: PRINT "Situation: SELECTED"
CASE STATE_MOVING: PRINT "Situation: MOVING"
CASE STATE_RESIZING: PRINT "Situation: RESIZING"
CASE STATE_ZOOMING: PRINT "Situation: ZOOMING"
END SELECT

_DISPLAY

mouseOldB = mouseB
LOOP UNTIL INKEY$ = CHR$(27) ' Exit with the ESC key
END SUB

FUNCTION MouseOverBBox (mx, my, bx, by, bw, bh)
IF mx >= bx AND mx <= bx + bw AND my >= by AND my <= by + bh THEN
MouseOverBBox = TRUE
ELSE
MouseOverBBox = FALSE
END IF
END FUNCTION

FUNCTION MouseResizeDirection (mx, my, bx, by, bw, bh)
DIM direction AS INTEGER
direction = 0
IF mx >= bx AND mx <= bx + 5 THEN direction = direction OR 1 ' Left
IF mx >= bx + bw - 5 AND mx <= bx + bw THEN direction = direction OR 2 ' Right
IF my >= by AND my <= by + 5 THEN direction = direction OR 4 ' Above
IF my >= by + bh - 5 AND my <= by + bh THEN direction = direction OR 8 ' Below
MouseResizeDirection = direction
END FUNCTION

SUB DrawCloseIcon (x, y)
LINE (x + 5, y + 5)-(x + 25, y + 25), _RGB32(255, 0, 0), B
LINE (x + 10, y + 10)-(x + 20, y + 20), _RGB32(255, 255, 255)
LINE (x + 10, y + 20)-(x + 20, y + 10), _RGB32(255, 255, 255)
END SUB

FUNCTION MouseOverCloseIcon (mx, my, x, y)
IF mx >= x + 5 AND mx <= x + 25 AND my >= y + 5 AND my <= y + 25 THEN
MouseOverCloseIcon = TRUE
ELSE
MouseOverCloseIcon = FALSE
END IF
END FUNCTION

SUB DrawThickBox (bx, by, bw, bh, thickness)
FOR i = 0 TO thickness - 1
LINE (bx - i, by - i)-(bx + bw + i, by + bh - 3 + i), _RGB32(255, 0, 0), B
NEXT
END SUB

SUB DrawMenuIcon (bw, bh)
LINE (bw + 5, bh + 5)-(bw + 25, bh + 25), _RGB32(0, 255, 0), B
LINE (bw + 10, bh + 10)-(bw + 20, bh + 10), _RGB32(255, 255, 255)
LINE (bw + 10, bh + 15)-(bw + 20, bh + 15), _RGB32(255, 255, 255)
LINE (bw + 10, bh + 20)-(bw + 20, bh + 20), _RGB32(255, 255, 255)
END SUB

FUNCTION MouseOverMenuIcon (mx, my, bw, bh)
IF mx >= bw + 5 AND mx <= bw + 25 AND my >= bh + 5 AND my <= bh + 25 THEN
MouseOverMenuIcon = TRUE
ELSE
MouseOverMenuIcon = FALSE
END IF
END FUNCTION

SUB DrawMenu (bw, bh)
LINE (bw + 5, bh + 30)-(bw + 105, bh + 130), _RGB32(0, 0, 255), B
PRINT "Menu item 1"
PRINT "Menu item 2"
PRINT "Menu item 3"
END SUB
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply




Users browsing this thread: 4 Guest(s)