При маштабировании, все дисплейные объекты увеличиваются переменной Zoom. При сохранении разности положений между, объектами и курсором, мы сам курсор
пропорционально зуму - уменьшаем. И при перемещении объектов, курсор тоже уменьшен. Затем увеличенные дисплейные объекты, мы смещаем относительно смещения мира. Которое происходит с помощью зажатой средней кнопки мышки.
Правильное маштабирование.
Перемещение и маштабирование мира работало нормально, но маштабитрование происходило отностительно начала мира. Мир хоть и можно было смещать, но маштаб происходил всё равно относительно начала мира, даже НЕ отностительно правого верхнего угла дисплея, а мира. Нужна была точка на дисплее относительно которой нужно маштабировать мир. Маштаб и так происходил, но смещение мира при маштабировании не было.
Смещение мира при маштабе происходит так:
1. Выбираем точку на дисплее, относительно которой будет маштаб. Это средина дисплея.
2. Узнаём смещение мира относительно центра вьювера
ScriptEditor.zWorldPosX := ScriptEditor.WorldPosX - Form1.GLSceneViewer1.Width/2;
ScriptEditor.zWorldPosY := ScriptEditor.WorldPosY - Form1.GLSceneViewer1.Height/2;
3. Вычисляем скорость (маштабирования смещения)
ScriptEditor.WorldZoom := ScriptEditor.Zoom / 1;
Дело сдесь в том, что скорость маштабирования разная. И растояние от нуля до текущего зума, не всегда равняется единице, а всегда больше или меньше. А при вычислении правильного положения мира:
ScriptEditor.WorldPosX := Form1.GLSceneViewer1.Width/2 + ScriptEditor.zWorldPosX * ZoomIndex;
ScriptEditor.WorldPosY := Form1.GLSceneViewer1.Height/2 + ScriptEditor.zWorldPosY * ZoomIndex;
в котором ZoomIndex должен быть максимум единицей ПРИ ОБНОВЛЕНИИ СМЕЩЕНИЯ МИРА ВРУЧНУЮ. Значит нужно сравнить пропорциональность маштабов, что мы и сделали:
ScriptEditor.WorldZoom := ScriptEditor.Zoom / 1;
Теперь зная с каким ускорением будет увеличиваться мир, мы вычисляем ZoomIndex
ZoomIndex := ScriptEditor.Zoom / ScriptEditor.WorldZoom;
Тоесть мир увеличивается и смещается с одной скоростью, хотя увеличение и смещение определяются разными методами. Здесь я расматривал метод смещения мира. Так как с маштабом всё и так было в порядке.
Теперь о логическом блоке.
Логический блок это объект который состоит из:
1. Заголовок
2. Тело, в которм хранятся контакты ввода и вывода информации
Контакт ввода и вывода это объекты имеющие название, активность и принадлежность к логическому блоку. Алгоритм рисования блока, генерируется в визуализаторе. Тоесть по базовым данным визуализатор строит блок:
1.Определяемся с шириной всего блока. В этом помогла одна замечательная сценовская функция
vNameWidth := ScriptEditor.HUDText.BitmapFont.CalcStringWidth(vName);
Хоть она хоть и возвращает Integer, что мне непонятно почему не Single, но она даёт ширину текста.
Потом узнаём размер самого длинного имени Ввода и Вывода.
// - Финальная Ширена блока
if (vNameWidth > (vNameInputWidth + vNameOutputWidth)) then
vWidth := 10 + vNameWidth
else
vWidth := 10 + vNameInputWidth + 10 + vNameOutputWidth;
2. Устанавливаем высоту заголовка
vHeightTitleBar := 20;
3. Рисуем текст - название заголовка блока
4. Нужно нарисовать рамку. Рамка это довольно не простая вещь в визуализации. Потому что у меня реализовано увеличение и уменьшение маштаба. Поэтому более широкий спрайт нарисованный споднизу основного спрайта, может подойти только при увеличении картинки. Но при уменьшении, когда размер рамки один пиксель, то на дисплее эта рамка рисуется через раз, потому что её перекрывает верхний главный спрайт. Поэтому для уменьшенной картинки я использую линии.
Рисую их средствами OpenGL. Это LoopLine.
Рамка (при увеличении) - спрайт
Рамка (при уменьшении) - линия
5. Нужно определиться с высотой тела блока. Для этого сравниваем количество вводов и выводов в блоке, и устанавливаем то что больше.
6. Визуализация рамки при увеличении и спрайта тела.
7. Рисуем названия вводов. Это цикл в котором считывается названия с вводов и ХУДТекстом визуализируется со смешением по высоте.
Каждый шаг это 20 пикселей.
8. Такой же подход и к визуализиции выводов.
Добавление вводов и выводов ничего нового в код не добавило, кроме подстраховочных обнулений выделеностей всех объектов которые можно выделить. Невозможно выделить одновременно несколько контактов. Это важное правило для соединения.
В основном всё работает по приципам заложеным в фундамент.
пропорционально зуму - уменьшаем. И при перемещении объектов, курсор тоже уменьшен. Затем увеличенные дисплейные объекты, мы смещаем относительно смещения мира. Которое происходит с помощью зажатой средней кнопки мышки.
Правильное маштабирование.
Перемещение и маштабирование мира работало нормально, но маштабитрование происходило отностительно начала мира. Мир хоть и можно было смещать, но маштаб происходил всё равно относительно начала мира, даже НЕ отностительно правого верхнего угла дисплея, а мира. Нужна была точка на дисплее относительно которой нужно маштабировать мир. Маштаб и так происходил, но смещение мира при маштабировании не было.
Смещение мира при маштабе происходит так:
1. Выбираем точку на дисплее, относительно которой будет маштаб. Это средина дисплея.
2. Узнаём смещение мира относительно центра вьювера
ScriptEditor.zWorldPosX := ScriptEditor.WorldPosX - Form1.GLSceneViewer1.Width/2;
ScriptEditor.zWorldPosY := ScriptEditor.WorldPosY - Form1.GLSceneViewer1.Height/2;
3. Вычисляем скорость (маштабирования смещения)
ScriptEditor.WorldZoom := ScriptEditor.Zoom / 1;
Дело сдесь в том, что скорость маштабирования разная. И растояние от нуля до текущего зума, не всегда равняется единице, а всегда больше или меньше. А при вычислении правильного положения мира:
ScriptEditor.WorldPosX := Form1.GLSceneViewer1.Width/2 + ScriptEditor.zWorldPosX * ZoomIndex;
ScriptEditor.WorldPosY := Form1.GLSceneViewer1.Height/2 + ScriptEditor.zWorldPosY * ZoomIndex;
в котором ZoomIndex должен быть максимум единицей ПРИ ОБНОВЛЕНИИ СМЕЩЕНИЯ МИРА ВРУЧНУЮ. Значит нужно сравнить пропорциональность маштабов, что мы и сделали:
ScriptEditor.WorldZoom := ScriptEditor.Zoom / 1;
Теперь зная с каким ускорением будет увеличиваться мир, мы вычисляем ZoomIndex
ZoomIndex := ScriptEditor.Zoom / ScriptEditor.WorldZoom;
Тоесть мир увеличивается и смещается с одной скоростью, хотя увеличение и смещение определяются разными методами. Здесь я расматривал метод смещения мира. Так как с маштабом всё и так было в порядке.
Теперь о логическом блоке.
Логический блок это объект который состоит из:
1. Заголовок
2. Тело, в которм хранятся контакты ввода и вывода информации
Контакт ввода и вывода это объекты имеющие название, активность и принадлежность к логическому блоку. Алгоритм рисования блока, генерируется в визуализаторе. Тоесть по базовым данным визуализатор строит блок:
1.Определяемся с шириной всего блока. В этом помогла одна замечательная сценовская функция
vNameWidth := ScriptEditor.HUDText.BitmapFont.CalcStringWidth(vName);
Хоть она хоть и возвращает Integer, что мне непонятно почему не Single, но она даёт ширину текста.
Потом узнаём размер самого длинного имени Ввода и Вывода.
// - Финальная Ширена блока
if (vNameWidth > (vNameInputWidth + vNameOutputWidth)) then
vWidth := 10 + vNameWidth
else
vWidth := 10 + vNameInputWidth + 10 + vNameOutputWidth;
2. Устанавливаем высоту заголовка
vHeightTitleBar := 20;
3. Рисуем текст - название заголовка блока
4. Нужно нарисовать рамку. Рамка это довольно не простая вещь в визуализации. Потому что у меня реализовано увеличение и уменьшение маштаба. Поэтому более широкий спрайт нарисованный споднизу основного спрайта, может подойти только при увеличении картинки. Но при уменьшении, когда размер рамки один пиксель, то на дисплее эта рамка рисуется через раз, потому что её перекрывает верхний главный спрайт. Поэтому для уменьшенной картинки я использую линии.
Рисую их средствами OpenGL. Это LoopLine.
Рамка (при увеличении) - спрайт
Рамка (при уменьшении) - линия
5. Нужно определиться с высотой тела блока. Для этого сравниваем количество вводов и выводов в блоке, и устанавливаем то что больше.
6. Визуализация рамки при увеличении и спрайта тела.
7. Рисуем названия вводов. Это цикл в котором считывается названия с вводов и ХУДТекстом визуализируется со смешением по высоте.
Каждый шаг это 20 пикселей.
8. Такой же подход и к визуализиции выводов.
Добавление вводов и выводов ничего нового в код не добавило, кроме подстраховочных обнулений выделеностей всех объектов которые можно выделить. Невозможно выделить одновременно несколько контактов. Это важное правило для соединения.
В основном всё работает по приципам заложеным в фундамент.
Комментариев нет:
Отправить комментарий