Как работать с изометрическим / ортогональным видом в Киви? - PullRequest
0 голосов
/ 26 февраля 2019

Изображение ниже представляет собой GridLayout 10 x 10 с кнопками.

https://i.stack.imgur.com/yZsJI.png

Я хотел бы создать такую ​​же сетку, но в изометрический / ортогональный 2-мерный вид .

Это означает, что каждая кнопка вместо квадрата может быть похожа на ромб, как показано на рисунке ниже:

enter image description here

Как я могу это сделать?

1 Ответ

0 голосов
/ 26 февраля 2019

Я не думаю, что на самом деле вы можете сделать трехмерное вращение на kivy UIX-виджетах, но вы можете выполнять 2D-вращение и масштабирование.Вот пример App, который делает это в методе build():

from kivy.app import App
from kivy.graphics.context_instructions import PushMatrix, Rotate, Scale, PopMatrix
from kivy.properties import BooleanProperty
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
import numpy as np


def matrixToNumpy(mat):
    a = []
    for i in range(4):
        b = []
        for j in range(4):
            b.append(mat[i*4+j])
        a.append(b)
    npmat = np.mat(a)
    return npmat


class MyButton(Button):

    def on_touch_down(self, touch):
        if not self.parent.touched:
            self.parent.touched = True
            if self.parent.mat is None:
                scale = matrixToNumpy(self.parent.sca.matrix)
                rotate = matrixToNumpy(self.parent.rot.matrix)
                self.parent.mat = np.matmul(rotate, scale)
                self.parent.inv_mat = self.parent.mat.I
            npTouch = np.mat([touch.x, touch.y, 0, 1.0])
            convTouch = np.matmul(npTouch, self.parent.inv_mat)
            touch.x = convTouch[0,0]
            touch.y = convTouch[0,1]
        return super(MyButton, self).on_touch_down(touch)

    def on_touch_up(self, touch):
        self.parent.touched = False
        return super(MyButton, self).on_touch_up(touch)


class MyGridLayout(GridLayout):
    touched = BooleanProperty(False)

    def __init__(self, **kwargs):
        super(MyGridLayout, self).__init__(**kwargs)
        self.mat = None
        self.inv_mat = None


class MyApp(App):
    def build(self):
        layout = MyGridLayout(cols=10)
        with layout.canvas.before:
            PushMatrix()
            layout.sca = Scale(1.0, 0.5, 1.0)
            layout.rot = Rotate(angle=45, axis=(0,0,1), origin=(400,300,0))
        with layout.canvas.after:
            PopMatrix()
        for i in range (1, 101):
            layout.add_widget(MyButton(text=str(i)))
        return layout

MyApp().run()

Я подозреваю, что с умным применением этих двух kivy.graphics.context_instructions, вы можете смоделировать то, что вы хотите.PushMatrix() и PopMatrix() ограничивают эффекты Scale и Rotate только MyGridLayout.Вы должны иметь возможность корректировать эти значения, используя ссылки layout.sca и layout.rot.

Я заметил после своего первоначального ответа, что Buttons выглядел хорошо, но больше не работал.Я добавил кучу кода для решения этой проблемы.Все элементы матрицы numpy предназначены только для приведения положения нажатия мыши в те же координаты, что и MyGridLayout.К сожалению, применение Canvas масштабирования и поворотов не учитывается автоматически событиями Kivy, поэтому требуется дополнительный код.

Вот как это выглядит: This is the resulting button array

...