javascriptjsonphaser-frameworkphaserjs

How can i make Nested Sizer Scrollable in RexUI


Here is code for creating an nested sizer form winner_joiner

   create() {
        
    
        this.dialog;
        var x = 1200,
          y = 1600,
          minWidth = 300,
          minHeight = undefined,
          table = {
            title: "Title/Title/Title",
            data: [
              {
                name: "AAA",
                content: "Hello",
              },
              {
                // icon1: this.add.image(1200, 1600, "btnStorage").setScale(2),
                // icon2: this.add.image(1300, 1600, "btnStorage").setScale(2),
                name: "BBBB",
                content: "World",
              },
            ],
          };
    
        var sizer = getTable(this, x, y, minWidth, minHeight, table);
        sizer.drawBounds(this.add.graphics(), 0xff0000);
      }
    }
    
   

     var getRow = function (scene, data) {
          var icon1 = scene.add.image(0, 0, "btnStorage").setScale(2);
          var icon2 = scene.add.image(0, 0, "btnStorage").setScale(2);
          var nameLabel = scene.add.text(0, 0, "ngu1", {
            fontSize: "50px",
            color: "white",
          });
          var contentLabel = scene.add.text(0, 0, "ngu2", {
            fontSize: "50px",
            color: "white",
          });
          var sizer = scene.rexUI.add
            .sizer({
              orientation: "x",
            })
        
            .add(icon1)
            .add(icon2)
            .add(nameLabel, 2, "left")
            .add(contentLabel, 5, "left");
          return sizer;
        };
        
        var getTable = function (scene, x, y, width, height, table) {
          var title = scene.add.text(0, 0, table.title, {
            fontSize: "60px",
            color: "white",
          });
        
          var sizer = scene.rexUI.add
            .sizer(x, y, width, height, {
              orientation: "y",
            })
            .add(title);
        
          var padding = {
            top: 10,
            //bottom: 10,
            left: 10,
            right: 10,
          };
          var data = table.data;
          for (var i = 0, cnt = data.length; i < 10; i++) {
            sizer.add(getRow(scene, data[i]), 0, "left", padding);
          }
          sizer.layout();
          return sizer;
        };

I want to make the whole nested sizer become an scrollable panel, but i really dont understand how nested sizer work. I try to look for any similar example on RexUi, but there is none.I try to add sizer into ScrollAblePanle but didnt success. Do anyone have suggestion?

Here my code for table function:

const setupTable = () => {
      this.table = this.add.rexGridTable(2900, 1500, 3500, 1700, {
        scrollMode: "vertical",
        cellHeight: 500,
        cellWidth: undefined,
        cellsCount: this.mergedInfo.length,
        columns: 6,
        cellVisibleCallback: onCellVisible.bind(this),
      });

      this.add.graphics().strokeRectShape(this.table.getBounds());
      this.table.setInteractive().setVisible(false);
      this.table.on("pointermove", function (pointer) {
        if (!pointer.isDown) {
          return;
        }
        var dx = pointer.x - pointer.prevPosition.x;
        var dy = pointer.y - pointer.prevPosition.y;
        this.table.addTableOXY(dx, dy).updateTable();
      });

      return this.table;
    };

    this.table = setupTable();

when i try to run it, my console.log show:'this.table.addTableOXY is not a function'


Solution

  • Well you would only need to add the "table" with the data-rows into the property panel as a child, of the scrollablePanel. Basically you can nest almost all rexUi controls in rexUi controls, you just need to set the correct property or call the correct function.
    But you need to be carful to set all the needed properties, since one missing or a wrong value can mess up the layout.

    Small Demo adding all parts together:
    (since this is abit complicated, I thought I would create a demo wiht all parts)

            class Demo extends Phaser.Scene {
                preload() {
                    this.load.scenePlugin({
                        key: 'rexuiplugin',
                        url: 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexuiplugin.min.js',
                        sceneKey: 'rexUI'
                    });
                }
                create() {
                    this.createTexureForIcons();
                    var x = config.width / 2,
                        y = config.height / 2,
                        minWidth = 300,
                        // Helper Data
                        data = '1'.repeat(10).split('').map((x, i) => {
                            return {
                                icon1Texture: `icon${Phaser.Math.RND.between(0, 4)}`,
                                icon2Texture: `icon${Phaser.Math.RND.between(0, 4)}`,
                                name: String.fromCharCode(97 + i).repeat(150)
                            };
                        });
    
                    // Scroll Panel
                    var scroller = this.rexUI.add.scrollablePanel({
                        x: config.width / 2,
                        y: config.height / 2,
                        width: 400,
                        height: 160,
                        background: this.rexUI.add.roundRectangle(0, 0, 2, 2, 10, 0xcdcdcd),
                        // add a table with the data as rows
                        panel: { child: this.createTable(data) },
                        slider: {
                            track: this.rexUI.add.roundRectangle(0, 0, 20, 10, 10, 0xffffff),
                            thumb: this.rexUI.add.roundRectangle(0, 0, 0, 0, 13, 0x0),
                        },
                        scroller: true,
                    })
                    .layout();
                }
    
                //Only for the Demo, create images/textures
                createTexureForIcons() {
                    let graphics = this.make.graphics();
                    let colors = [0xffffff, 0xffff00, 0xff0000, 0x00ff00, 0x0000ff];
                    colors.forEach((color, idx) => {
                        graphics.fillStyle(color);
                        graphics.fillRect(0, 0, 40, 40);
                        graphics.generateTexture(`icon${idx}`, 40, 40);
                    });
                }
    
                createTable(data) {
                    // Sizer/Container for the items
                    var sizer = this.rexUI.add.sizer(0, 0, undefined, undefined, {
                        orientation: 'y',
                    });
    
                    // add a line per data entry
                    data.forEach(entry => {
                        sizer.add(this.createRow(entry), 0, 'left');
                    });
                    return sizer.layout();
                }
    
                createRow(entry) {
                    // create icons to add
                    var icon1 = this.add.image(0, 0, entry.icon1Texture);
                    var icon2 = this.add.image(0, 0, entry.icon2Texture);
                    // padding for around the icons
                    var imagePadding = { left: 5, right: 5, top: 5, bottom: 5 };
    
                    // create basic phaser Text-GameObject
                    var basicLabel = this.add.text(0, 0, entry.name, {
                        fontSize: '24px',
                        color: 'black'
                    });
    
                    // create rexUI Lable with phaser Text-GameObject
                    var nameLabel = this.rexUI.add.label({
                        orientation: 1,
                        width: 300,
                        // prepare Text - GameObject for wrapping
                        text: this.rexUI.wrapExpandText(basicLabel),
                        // Set Text Wrapping for character wrapping
                        wrapText: 2,
                        // needed for wrapping to work correct
                        expandTextWidth: true,
                    });
    
                    // Create Row with two images and one text Label
                    var sizerRow = this.rexUI.add.sizer({ orientation: 'x'})
                        .add(icon1, { proportion: 0, expand: false, fitRatio: false, padding: imagePadding })
                        .add(icon2, { proportion: 0, expand: false, fitRatio: false, padding: imagePadding })
                        .add(nameLabel, {
                            align: 'left',
                            padding: { left: 10, right: 10, top: 10, bottom: 10 },
                            expand: true,
                        });
                    return sizerRow;
                }
            }
    
            var config = { width: 510, height: 180, scene: Demo };
            new Phaser.Game(config);
            
            console.clear();
    <script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

    As an alternative you could use the gridSizer(link to the documenation), instead of the sizer (for the table ), if you need multiple images in a row/column style, with special dimensions, or in a grid like fashion (here is an interesting demo showcasing the gridSizer).

    Tipp: The documentation is adequate, but if you want to understand the controls better and faster, it is easier to checkout, all the provided demos, which are linked at the top of each documentation page. Especially because you can test them right away inBrowser.