Правильный скроллиинг

Версия Minecraft
1.7.10
Доброго времени суток. Попытался сделать скролл в гуискрин, работает почти неплохо, но есть несколько моментов: 1) отображается не полный список предметов из листа, от сюда следует вопрос: как правильно это сделать. 2) как можно отображать какую-то часть от предмета, к сожалению сейчас рисуется он целиком из-за этого появляются пустые строки.

Видео демонстрация:

P.S: ограничения на движения скролла убрал специально. чтобы показать сколько еще предметов не поместилось.

Размер скролла и размер всего листа я определяю след. строками кода:
Java:
listSize = (int) (Math.ceil(itemsList.size() / 7.0D) * 21 * 1.7F);
        scrollHeight = (int) ((blockHeight - 25) / listSize * (blockHeight - 25));
7.0D - т.к. на одной строке размещается 7 элементов
21 = 16 + 5 (16 длинна отрисовки блока + 5 отступа)
1.7 - масштаб

Весь код:
Java:
    public BlockerGui() {
        mc = Minecraft.getMinecraft();
        sc = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
        super.width = mc.displayWidth / sc.getScaleFactor();
        super.height = mc.displayHeight / sc.getScaleFactor();
        currentScroll = 0;
        itemsList = ClientHandler.objs;
        blockWidth = 250;
        blockHeight = 155;
        guiLeft = width / 2 - blockWidth / 2;
        guiTop = height / 2 - blockHeight / 2;
        //rows = Math.ceil(itemsList.size() / 7.0D);
        listSize = (int) (Math.ceil(itemsList.size() / 7.0D) * 21 * 1.7F);
        scrollHeight = (int) ((blockHeight - 25) / listSize * (blockHeight - 25));
        maxScrolly = guiTop + blockHeight - scrollHeight - 5;
        minScrolly = guiTop + 20;

        currentScroll = minScrolly;
        System.out.println(itemsList.size());
    }

    @Override
    public void drawScreen(int i, int j, float f) {
        guiLeft = width / 2 - blockWidth / 2;
        guiTop = height / 2 - blockHeight / 2;
        maxScrolly = guiTop + blockHeight - scrollHeight - 5;
        minScrolly = guiTop + 20;
        handleMouse();
        FontRenderer renderer = mc.fontRenderer;
        int mouseXOffset = i - guiLeft;
        int mouseYOffset = j - guiTop;
        if(Mouse.isButtonDown(0)) {
            if(mouseXOffset >= blockWidth - 7 && mouseXOffset < blockWidth - 2 && mouseYOffset >= 20 && mouseYOffset < maxScrolly + scrollHeight - guiTop - 5) {
                isScrolling = true;
            }
        } else {
            isScrolling = false;
        }

        if(isScrolling && hasScroll() && lastMouseClick != 0) {
            currentScroll -= lastMouseClick - j;
        }
//        if (currentScroll > maxScrolly) currentScroll = maxScrolly;
//        else if (currentScroll < minScrolly) currentScroll = minScrolly;

        lastMouseClick = j;

        //draw gui
        Gui.drawRect(guiLeft, guiTop, guiLeft + blockWidth, guiTop + blockHeight, new Color(0x7A000000, true).getRGB());
        int lineStart = width / 2 - (renderer.getStringWidth(guiName) + 7 ) / 2;
        drawHorizontalLine(lineStart, (int) (lineStart + renderer.getStringWidth(guiName) + 3.5), guiTop + renderer.FONT_HEIGHT + 5, new Color(0x35FF5E).getRGB());

        //draw Items
        drawBoxWithItems(guiLeft, guiTop + 20);

        super.drawScreen(i, j, f);
    }

    private void drawBoxWithItems(int startBoxX, int startBoxY) {
        drawScroll(startBoxX + blockWidth);

        int itemX = 0;
        float scaleItems = 1.7F;
        for(int i = 0; i< itemsList.size(); i++) {
            ItemStack item = itemsList.get(i).getIs();
            if(item != null) {
                int scrollOffset = currentScroll - guiTop - 20;
                int curPos = (int) (21 * scaleItems) * (i / 7) + startBoxY - scrollOffset;
                if(curPos >= startBoxY && curPos - (21 * scaleItems) <= blockHeight - 5) {
                    item.setItemDamage(itemsList.get(i).getData());
                    GL11.glPushMatrix();
                    GL11.glTranslatef(startBoxX + itemX + 5, curPos, scaleItems);
                    GL11.glScaled(scaleItems, scaleItems, scaleItems);
                    RenderHelper.disableStandardItemLighting();
                    itemRender.renderItemAndEffectIntoGUI(mc.fontRenderer, mc.getTextureManager(), item, 0, 0);
                    GL11.glPopMatrix();
                }
                if (itemX > 16 * 7 * scaleItems) {
                    itemX = 0;
                } else {
                    itemX += 21 * scaleItems;
                }
            }
        }
        RenderHelper.enableStandardItemLighting();
    }

    public void handleMouse() {
        int dw = Mouse.getEventDWheel();
        if(hasScroll()) {
            if(dw < 0) {
                dw = 1;
            } else if(dw > 0) {
                dw = -1;
            }
            if(dw != 0) {
                currentScroll += dw * 3;
                if (currentScroll > maxScrolly) currentScroll = maxScrolly;
                else if (currentScroll < minScrolly) currentScroll = minScrolly;
            }
        }
    }

    private void drawScroll(int x) {
        if(hasScroll()) {
            Gui.drawRect(x-5, currentScroll, x-2, currentScroll + scrollHeight, new Color(0x3F9CFF).getRGB());
        }
    }

    private boolean hasScroll() {
        return listSize > blockHeight - 25;
    }
 
7,099
324
1,509
Стоит сначала разработать математическую модель скроллинга исходя их простых очевидных определений, типо:
ползунок может перемещаться в пределах скроллбара
крайние точки положения контента ограничены областью отображения
положение контента пропорционально положению ползунка

Хорошей идеей будет визуально изобразить модель, типо, нарисовать схематично частные случаи положения ползунка и контента

Потом можно приступить к переносу модели в реализацию кодом
 

will0376

Токсичная личность
2,059
55
572
их простых очевидных определений
[offtop]Ых. пытался в своё время так для OB сделать... Плюнул, переписал под страницы...[/offtop]
По теме: Как вариант - можешь поискать моды с готовой реализацией
 

tox1cozZ

aka Agravaine
8,454
598
2,890
 
Стоит сначала разработать математическую модель скроллинга исходя их простых очевидных определений, типо:
ползунок может перемещаться в пределах скроллбара
крайние точки положения контента ограничены областью отображения
положение контента пропорционально положению ползунка

Хорошей идеей будет визуально изобразить модель, типо, нарисовать схематично частные случаи положения ползунка и контента

Потом можно приступить к переносу модели в реализацию кодом
Тыакс, ток сегодня появилось время, чтоб вернуться к этой штукенции. На счет мат-ой модели... С самим ползункой вроде как разобрался. На колесико крутится как надо, на перетаскивание мышкой с зажатой клавишой тоже работает. Тут вопросов не возникает. Самое сложное для меня это правильно отрисовать предметы в зависимости от положения скролла. Как рассуждал я:
1) нам нужен Лист объектов(наши предметы, которые мы будет отображать, на одной строке 7 предметов), соответственно, нам надо понять сколько всего места замет весь лист, для этого считаем такс:

Java:
listSize = (int) (Math.ceil(itemsList.size() / 7.0D) * 21 * 1.7F);
7 - кол-во предметов на строку. идет округление в большую сторону, т.к. нам возможно будет одна неполная строка. 21 = 16 текстура предмета + отступ от нее 5. Скейл = 1.7
Размер ползунка считаем по такой формуле:
Java:
scrollHeight = (int) ((blockHeight - 25) / listSize * (blockHeight - 25));
blockHeight - размер гуискрин. 25 = 20 отступ сверху и 5 отступ снизу.
Теперь пытаемся это рисовать:

Java:
int scrollOffset = currentScroll - guiTop - 20;
                int curPos = (int) (21 * scaleItems) * (i / 7) + startBoxY - scrollOffset;
                if(curPos >= startBoxY && curPos - (21 * scaleItems) <= blockHeight - 5) {
                    item.setItemDamage(itemsList.get(i).getData());
                    GL11.glPushMatrix();
                    GL11.glTranslatef(startBoxX + itemX + 5, curPos, scaleItems);
                    GL11.glScaled(scaleItems, scaleItems, scaleItems);
                    RenderHelper.disableStandardItemLighting();
                    itemRender.renderItemAndEffectIntoGUI(mc.fontRenderer, mc.getTextureManager(), item, 0, 0);
                    GL11.glPopMatrix();
                }
                if (itemX > 16 * 7 * scaleItems) {
                    itemX = 0;
                } else {
                    itemX += 21 * scaleItems;
                }
currentScroll - текущее положение скролла(берется верхняя координата y)
В условии проверю, попадает ли curPos в область, где можно отрисовывать предметы. Вроде как работает(но неправильно, видос выше), но кажется я неправильно использую положение скролла или вовсе что-то не учел. Прошу помощи =(
 
Спасибо, одним вопросом меньше.
 
Сверху