Palette not showing and data problem

Palette not showing and data problem

vonbinderhosen
Participant Participant
291 Views
1 Reply
Message 1 of 2

Palette not showing and data problem

vonbinderhosen
Participant
Participant

Hi y'all. I've read through a ton of palette and data transit problems and I can't seem to get this right. I've messed with it a variety of ways.

Problem #1. I can get the palette to show, but when I try to send data, it doesn't seem to fire the notify handler. That only works if I don't have a stop(context) method

Problem #2. If I add the stop(context) method, the palette doesn't show. Via logging I can tell it's just very quickly running the palette and destroying it.

 

Would love any ideas for one or the other.

 

I think these are the key pieces of code.

 

Palette HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Jitter size configuration</title>
    <script>
        function logDebugMessage(message) {
            const debugDiv = document.getElementById('debugMessages');
            debugDiv.innerHTML += `<p>${message}</p>`;
        }

        function sendValues() {
            const minSize = document.getElementById('minSize').value;
            const maxSize = document.getElementById('maxSize').value;
            var args = {
                minSize : minSize,
                maxSize : maxSize
                };
            logDebugMessage(`Sending data: ${JSON.stringify(args)}`);
            adsk.fusionSendData("send", JSON.stringify(args));
            logDebugMessage("Data sent");
            
            // adsk.fusionSendData("send", JSON.stringify(args)).then((result) =>
            //     document.getElementById('returnValue').innerHTML = `Result: ${result}`
            // );
        }

        window.fusionJavaScriptHandler = {handle: function(action, data){
            try {
                if (action == 'send') {
					document.getElementById('p1').innerHTML = data;
				}
				else if (action == 'debugger') {
                    debugger;
				}
				else {
					return 'Unexpected command type: ' + action;
                }
            } catch (e) {
                console.log(e);
                console.log('exception caught with command: ' + action + ', data: ' + data);
            }
            return 'OK';
        }};
    </script>
</head>
<body>
    <p id="xxx">Active Document Name</p>

    <label for="minSize">Minimum cut size (cm):</label>
    <input type="number" id="minSize" name="minSize" min="1" max="50" value="10" step="1">
    <br />
    <label for="maxSize">Maximum cut size (cm):</label>
    <input type="number" id="maxSize" name="maxSize" min="1" max="100" value="20" step="1">
    <br />
    <button onclick="sendValues()">Submit</button>
    <br />
    <div id="returnValue" style="margin-top: 20px; color: red; font-size: small;">
    </div>
    <br />
    <div id="p1" style="margin-top: 20px; color: green; font-size: small;">
    </div>
    <br />
    <div id="debugMessages" style="margin-top: 20px; color: blue; font-size: small;">
        <strong>Debug Messages:</strong>
    </div>
</body>
</html>

 

 

Python script:

class JitterProcessor:
    def __init__(self, ui):
        ...
        self.ui = ui
        self.palette = None
        self.handlers = []

    ...

    def getUserInputSize(self):
        log_to_file("guis 1")
        # Set up and display the web palette
        htmlFilePath = 'file:///' + os.path.join(os.path.dirname(__file__), 'EdgeJitterPalette_sizeInput.html').replace('\\', '/')
        self.palette = self.ui.palettes.itemById('cutSizePalette')
        if not self.palette:
            self.palette = self.ui.palettes.add('cutSizePalette', 'Jitter size configuration', htmlFilePath, True, True, True, 300, 150)
            
            # Attach the event handler
            log_to_file("guis 2a")
            handler = self.UserInputEventHandler() #self.callbackFromSizeInput)
            self.palette.incomingFromHTML.add(handler)
            self.handlers.append(handler)  # Keep a reference to avoid garbage collection

            
            # Add handler to CloseEvent of the palette.
            onClosed = self.UserInputCloseEventHandler()
            self.palette.closed.add(onClosed)
            self.handlers.append(onClosed)   
        else:
            log_to_file("guis 2b")
            self.palette.isVisible = True

    ...

    def callbackFromSizeInput(self, minSize, maxSize):
        if minSize is None or maxSize is None:
            return  # Handle error or invalid input
        
        self.palette.isVisible = False

        self.minSize = minSize
        self.maxSize = maxSize

        self.recursiveCut(self.selectedLine, self.startPoint, self.endPoint, self.dominantAxis, 
                          self.minSize, self.maxSize)

    def run(self):
        ...
        log_to_file("getUserInputSize")
        self.getUserInputSize()


    def stop(self):
        try:        
            # Delete the palette created by this add-in.
            palette = self.ui.palettes.itemById('cutSizePalette')
            if palette:
                palette.deleteMe()
        except:
            if self.ui:
                self.ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

    
    # ----- INNER CLASSES -----

    class UserInputEventHandler(adsk.core.HTMLEventHandler):
        def __init__(self):
            log_to_file("eventHandler init")
            super().__init__()
            # self.callback = callback

        def notify(self, args):
            log_to_file("notify1")
            try:
                # This method will be called when an HTML event is fired
                htmlArgs = adsk.core.HTMLEventArgs.cast(args)
                data = json.loads(htmlArgs.data)

                log_to_file("notify2: Data received:", data)
                # Expected data format: 'minSize=10&maxSize=20'
                minSize, maxSize = map(float, [x.split('=')[1] for x in data.split('&')])
                # if minSize <= 0 or maxSize >= 100 or minSize > maxSize:
                #     ui = adsk.core.Application.get().userInterface
                #     ui.messageBox("Invalid input sizes. Ensure min is less than max and within the valid range.")
                # else:
                #     self.callback(minSize, maxSize)

            except:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))        

            return "hi"
    
    # Event handler for the palette close event.
    class UserInputCloseEventHandler(adsk.core.UserInterfaceGeneralEventHandler):
        def __init__(self):
            super().__init__()
        def notify(self, args):
            log_to_file("uic1")
            try:
                _ui.messageBox('Close button is clicked.') 
            except:
                _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

    ## EVERYONE LOVES THE END OF CLASS

# This is Fusion 360's main method
def run(context):
    log_to_file("run")
    global _ui, _processor
    _ui = adsk.core.Application.get().userInterface
    _processor = JitterProcessor(_ui)
    _processor.run()

def stop(context):
    log_to_file("stop")
    _processor.stop()

def log_to_file(message):
    # Define the path for the log file
    log_file_path = os.path.join(os.path.expanduser("~"), "fusion_debug_log.txt")
    timestamp = datetime.now().strftime("%H:%M:%S")
    # Write the message to the file
    with open(log_file_path, "a") as log_file:
        log_file.write(f"[{timestamp}] {message}\n")

 

Thank you!

 

0 Likes
292 Views
1 Reply
Reply (1)
Message 2 of 2

vonbinderhosen
Participant
Participant

Unfortunately I got no responses here. Buttt I did eventually figure it out. First, I found this post by kandennti. It was initially confusing because it seemed to focus on the async browser behavior as a key factor, which maybe it was for them, but not for me. I had tried sync and async in the browser, and it didnt matter. In fact, once I got this working, that still didn't matter. The key trick to get adsk.fusionSendData working was on the python side. There does not seem to be any documentation that explains the need for all the command input set up and usage. That was the required bit to get it working.

 

I got there by grabbing their included example ("PassInitialValuesExample.zip" on the linked post) and running that as-is (zero edits). It worked immediately. Then, I kept stripping out bits until I figure out which was the part that broke it. Then I added that part to my script and it started working.

Now, that was a huge feeling! But after it, I was trying to follow the API docs to understand more about command inputs and realized the need for custom HTML palette was almost moot. I figured out that I can add custom visual controls using the CommandInputs such as addFloatSliderCommandInput and buttons and that's even simpler. So I've moved over to that and scrapped the palette, even thought it was working. C'est la vie!

0 Likes