完成value搜索

This commit is contained in:
锦恢 2024-08-29 23:17:48 +08:00
parent 9f50214cbb
commit f74fc31aaf
22 changed files with 522 additions and 105 deletions

14
package-lock.json generated
View File

@ -12,7 +12,7 @@
"version": "0.1.0",
"dependencies": {
"core-js": "^3.8.3",
"element-plus": "^2.5.6",
"element-plus": "^2.6.3",
"lodash.get": "^4.4.2",
"mitt": "^3.0.1",
"onml": "^2.1.0",
@ -5170,9 +5170,9 @@
"dev": true
},
"node_modules/element-plus": {
"version": "2.5.6",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.5.6.tgz",
"integrity": "sha512-zctKTiyIDmcnMp3K5WG1hglgraW9EbiCLiIDVtaMCS5mPMl2fRKdS0vOFGnECIq9taFoxnyoDwxHD81nv0B4RA==",
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.6.3.tgz",
"integrity": "sha512-U4L/mr+1r+EmAUYUHrs0V/8hHMdBGP07rPymSC72LZCN4jK1UwygQYICegTQ5us4mxeqBvW6wfoEfo003fwCqw==",
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.1",
@ -14633,9 +14633,9 @@
"dev": true
},
"element-plus": {
"version": "2.5.6",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.5.6.tgz",
"integrity": "sha512-zctKTiyIDmcnMp3K5WG1hglgraW9EbiCLiIDVtaMCS5mPMl2fRKdS0vOFGnECIq9taFoxnyoDwxHD81nv0B4RA==",
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.6.3.tgz",
"integrity": "sha512-U4L/mr+1r+EmAUYUHrs0V/8hHMdBGP07rPymSC72LZCN4jK1UwygQYICegTQ5us4mxeqBvW6wfoEfo003fwCqw==",
"requires": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.1",

View File

@ -9,7 +9,7 @@
},
"dependencies": {
"core-js": "^3.8.3",
"element-plus": "^2.5.6",
"element-plus": "^2.6.3",
"lodash.get": "^4.4.2",
"mitt": "^3.0.1",
"onml": "^2.1.0",

View File

@ -9,9 +9,11 @@ export const StaticCursor = reactive({
left: 0,
updateLabel(timescale) {
this.label = formatTime(this.currentTime, timescale);
this.show = true;
},
updateLeft() {
this.left = calcCursorLeft(this.currentTime);
this.show = true;
}
});

View File

@ -87,8 +87,8 @@
<div class="setting-option">
<span class="option-title" style="width: 150px;">{{ t('display-signal-info-scope') }}</span>
<el-checkbox-group v-model="globalSetting.displaySignalInfoScope" size="default">
<el-checkbox-button label="width" border>{{ t('display-signal-info-scope.width') }}</el-checkbox-button>
<el-checkbox-button label="parent" border>{{ t('display-signal-info-scope.parent') }}</el-checkbox-button>
<el-checkbox-button value="width" border>{{ t('display-signal-info-scope.width') }}</el-checkbox-button>
<el-checkbox-button value="parent" border>{{ t('display-signal-info-scope.parent') }}</el-checkbox-button>
</el-checkbox-group>
</div>

View File

@ -1,5 +1,12 @@
import { globalLookup } from "@/hook/global";
import { reactive } from "vue";
import { contextmenu } from "./handle-contextmenu";
import i18n from '@/i18n/index';
import { ElMessage } from "element-plus";
import { findViewIndexByLink } from "@/hook/wave-container-view";
const { t } = i18n.global;
// 从 globalLookup.currentWiresRenderView 中可以获取当前的分组情况
export function getCurrentGroups() {
@ -16,3 +23,64 @@ export const existGroup = reactive({
this.display = false;
}
});
/**
*
* @param {WaveRenderSidebarItem} group
* @param {WireItem} signal
*/
function inGroup(group, signal) {
for (const child of group.children) {
if (child.signalInfo.link === signal.link) {
return true;
}
}
return false;
}
/**
*
* @param {WaveRenderSidebarItem} group
*/
export function joinGroup(group) {
const signal = contextmenu.currentWire;
if (signal === undefined) {
return;
}
// 检查是否已经在里面了
if (inGroup(group, signal)) {
ElMessage({
message: t('context-menu.cannot-join-repeat-group'),
type: 'warning',
plain: true,
showClose: true,
duration: 0
});
return;
}
// 加入 group 中
group.children.push({
signalInfo: {
name: signal.name,
link: signal.link,
size: signal.size,
},
groupInfo: {
name: '',
color: '',
collapse: false
},
renderType: 0,
children: []
});
// 删除的逻辑参照 wave-container-view.js delete 函数
const renderView = globalLookup.currentWiresRenderView;
const i = findViewIndexByLink(signal.link);
const tailElements = renderView.slice(i + 1);
renderView.length = i;
tailElements.forEach(view => renderView.push(view));
}

View File

@ -7,6 +7,7 @@
:key="index"
class="group-item"
:style="getItemStyle(item)"
@click="onClick(item)"
>
<span class="iconfont icon-group"></span>
&ensp;
@ -32,6 +33,7 @@ import { contextmenu } from './handle-contextmenu';
import { currentGroups } from './manage-group';
import { globalLookup } from '@/hook/global';
import { useI18n } from 'vue-i18n';
import { joinGroup } from './exist-group';
const { t } = useI18n();
@ -61,6 +63,10 @@ function getItemName(view) {
return name;
}
function onClick(group) {
joinGroup(group);
}
</script>
<style scoped>

View File

@ -192,6 +192,7 @@ function handleSidebarGlobalClick() {
display: flex;
justify-content: space-around;
align-items: center;
transition: var(--animation-5s);
}
.signal-color-vendor > span {

View File

@ -6,7 +6,10 @@
}"
>
<div class="display-signal-item">
<div class="signal-color-vendor">
<div
class="signal-color-vendor"
:class="{ 'search-active': toolbarValueSearch.resultLinkSet.has(props.view.signalInfo.link) }"
>
<span :class="makeSignalIconClass(signalInfo)"></span>
</div>
@ -47,6 +50,7 @@ import { defineComponent, computed } from 'vue';
import { contextmenu } from './handle-contextmenu';
import { sidebarSelectedWires } from '@/hook/sidebar-select-wire';
import { FormatValueRender } from '@/hook/wave-view/toolbar/renderFormat';
import { toolbarValueSearch } from '../toolbar/value-search';
defineComponent({ name: 'signal-item' });
@ -117,4 +121,10 @@ function makeCurrentValue(link) {
display: flex;
width: 100%;
}
.signal-color-vendor.search-active {
background-color: var(--main-color) !important;
transition: var(--animation-5s);
}
</style>

View File

@ -1,6 +1,7 @@
import { globalLookup } from "@/hook/global";
import { calcCursorLeft, StaticCursor } from "../render/cursor";
import { sidebarSelectedWires } from "@/hook/sidebar-select-wire";
import { updateWireCurrentValue } from "@/hook/utils";
/**
@ -9,15 +10,29 @@ import { sidebarSelectedWires } from "@/hook/sidebar-select-wire";
* @param {number} leftMargin 移动后的该时间点距离左侧多少px
* @param {Pstate} pstate
*/
function moveto(time, leftMargin, pstate) {
export function moveto(time, leftMargin, pstate) {
StaticCursor.show = true;
StaticCursor.currentTime = time;
pstate.oldXOffset = pstate.xOffset;
const { width, xOffset, xScale, tgcd, timescale } = pstate;
pstate.xOffset = leftMargin - (time / tgcd) * xScale;
const { width, xOffset, xScale, tgcd, timescale } = pstate;
let nextOffsetX = leftMargin - (time / tgcd) * xScale;
const sidebarWidth = pstate.sidebarWidth;
if (nextOffsetX >= sidebarWidth) {
nextOffsetX = sidebarWidth - 20;
}
pstate.oldXOffset = pstate.xOffset;
pstate.xOffset = nextOffsetX;
// 改变静态信标
StaticCursor.updateLeft();
StaticCursor.updateLabel(pstate.timescale);
// 更新所有轨道的数字
updateWireCurrentValue(time);
// 更换渲染视图
globalLookup.render();
}
@ -132,7 +147,7 @@ export function makeLocation() {
* @param {number} time
* @return {number}
*/
function bisearch(wave, time) {
export function bisearch(wave, time) {
const times = wave.map(p => p[0]);
// 二分查找,并将结果存入 i

View File

@ -6,7 +6,7 @@
@change="onSignalModalUpdate"
>
<!-- 数字模式 -->
<el-radio-button :label="0">
<el-radio-button :value="0">
<el-tooltip
effect="dark"
:content="t('toolbar.modal.common-digital')"
@ -17,7 +17,7 @@
</el-tooltip>
</el-radio-button>
<!-- 阶梯模拟 -->
<el-radio-button :label="1">
<el-radio-button :value="1">
<el-tooltip
effect="dark"
:content="t('toolbar.modal.ladder-analog')"
@ -26,7 +26,7 @@
><span class="iconfont icon-ladder-analog"></span></el-tooltip>
</el-radio-button>
<!-- 折线模拟 -->
<el-radio-button :label="2">
<el-radio-button :value="2">
<el-tooltip
effect="dark"
:content="t('toolbar.modal.line-analog')"

View File

@ -0,0 +1,199 @@
/**
* @description 搜索数值的每一个结果的数据结构
* @typedef {Object} toolbarSearchResultItem
* @property {string} name
* @property {string} link
* @property {number} width
* @property {string} type
* @property {number} value
*/
import { globalLookup } from "@/hook/global";
import { sidebarSelectedWires } from "@/hook/sidebar-select-wire";
import { reactive, ref } from "vue";
import { bisearch, moveto } from "./cursor-location";
import { StaticCursor } from "../render/cursor";
import { FormatValueRender, JSValueRender } from "@/hook/wave-view/toolbar/renderFormat";
import { ElMessage } from "element-plus";
import i18n from '@/i18n/index';
const { t } = i18n.global;
export const searchMode = ref(1);
export const valueSearchText = ref(t('toolbar.search.value.searching'));
export const toolbarValueSearch = reactive({
content: '',
displayResult: false,
mouseOnResult: false,
/**
* @type {toolbarSearchResultItem[]}
*/
searchResult: [],
/**
* @type {Set<string>}
*/
resultLinkSet: new Set(),
/**
* @description 当前选择的索引
*/
cursorIndex: -1
});
function toPrevValue() {
// TODO: 空间换时间,提升性能
const prevTimes = [];
const currentT = StaticCursor.currentTime;
// StaticCursor.updateLabel(currentT);
// StaticCursor.updateLeft();
const searchContent = toolbarValueSearch.content.trim();
for (const link of globalLookup.sidebarSelectedWireLinks) {
const chango = globalLookup.chango[link];
const signal = globalLookup.link2CurrentWires.get(link);
const valueRender = new FormatValueRender(link, signal.size, '');
const { wave } = chango;
let i = bisearch(wave, currentT);
console.log(i);
// 往前寻找
while (i >= 0) {
const [t, val, mask] = wave[i];
const valString = mask === 1 ? 'x' : valueRender.render(val, -1);
console.log(val, valString, wave[i]);
if (valString === searchContent && t != currentT) {
break;
}
i --;
}
if (i >= 0 && wave[i][0] < currentT) {
prevTimes.push(wave[i][0]);
}
}
if (prevTimes.length > 0) {
const preT = Math.max(...prevTimes);
const pstate = globalLookup.pstate;
moveto(preT, (pstate.width + pstate.sidebarWidth) / 2, pstate);
} else {
valueSearchText.value = t('toolbar.search.value.already-to-head');
}
}
function toNextValue() {
const prevTimes = [];
const currentT = StaticCursor.currentTime;
// StaticCursor.updateLabel(currentT);
// StaticCursor.updateLeft();
const searchContent = toolbarValueSearch.content.trim();
for (const link of globalLookup.sidebarSelectedWireLinks) {
const chango = globalLookup.chango[link];
const signal = globalLookup.link2CurrentWires.get(link);
const valueRender = new FormatValueRender(link, signal.size, '');
const { wave } = chango;
let i = bisearch(wave, currentT);
const length = wave.length;
// 往后寻找
while (i < length) {
const [t, val, mask] = wave[i];
const valString = mask === 1 ? 'x' : valueRender.render(val, -1);
console.log(val, mask, valString);
if (valString === searchContent && t != currentT) {
break;
}
i ++;
}
if (i < length && wave[i][0] > currentT) {
prevTimes.push(wave[i][0]);
}
}
if (prevTimes.length > 0) {
const preT = Math.min(...prevTimes);
const pstate = globalLookup.pstate;
moveto(preT, (pstate.width + pstate.sidebarWidth) / 2, pstate);
} else {
valueSearchText.value = t('toolbar.search.value.already-to-tail');
}
}
function toPrevName() {
// 清空
sidebarSelectedWires.clear();
const currentIndex = toolbarValueSearch.cursorIndex;
const searchResultNum = toolbarValueSearch.searchResult.length;
const targetIndex = (currentIndex - 1 + searchResultNum) % searchResultNum;
if (targetIndex !== currentIndex) {
toolbarValueSearch.cursorIndex = targetIndex;
const { link } = toolbarValueSearch.searchResult[targetIndex];
sidebarSelectedWires.add(link);
}
}
function toNextName() {
// 清空
sidebarSelectedWires.clear();
const currentIndex = toolbarValueSearch.cursorIndex;
const searchResultNum = toolbarValueSearch.searchResult.length;
const targetIndex = (currentIndex + 1) % searchResultNum;
if (targetIndex !== currentIndex) {
toolbarValueSearch.cursorIndex = targetIndex;
const { link } = toolbarValueSearch.searchResult[targetIndex];
sidebarSelectedWires.add(link);
}
}
export function onClickPrev() {
if (globalLookup.sidebarSelectedWireLinks.size === 0 || toolbarValueSearch.content.trim().length === 0) {
return;
}
switch (searchMode.value) {
case 0:
toPrevValue();
break;
case 1:
toPrevName();
break;
default:
break;
}
}
export function onClickNext() {
if (globalLookup.sidebarSelectedWireLinks.size === 0 || toolbarValueSearch.content.trim().length === 0) {
return;
}
switch (searchMode.value) {
case 0:
toNextValue();
break;
case 1:
toNextName();
break;
default:
break;
}
}

View File

@ -1,87 +1,86 @@
<template>
<div class="value-search">
<div class="value-search"
>
<div>
<el-radio-group
v-model="searchMode"
style="border-radius: 1.2em;"
>
<el-radio-button :label="0">
<el-radio-button :value="0">
<span>{{ t('toolbar.search.value') }}</span>
</el-radio-button>
<el-radio-button :label="1">
<el-radio-button :value="1">
<span>{{ t('toolbar.search.name') }}</span>
</el-radio-button>
</el-radio-group>
</div>
<div class="value-input-wrapper">
<div
class="value-input-wrapper"
:style="inputStyle"
>
<el-input
v-model="searchManage.content"
v-model="toolbarValueSearch.content"
@input="safeSearch"
@focus="searchManage.displayResult = true"
@blur="searchManage.displayResult = false"
@keydown.enter="onEnter()"
></el-input>
<transition name="collapse-from-top">
<div
v-show="searchManage.displayResult || searchManage.mouseOnResult"
class="toolbar-search-container"
>
<el-scrollbar
height="300px"
width="100%"
@mouseenter="searchManage.mouseOnResult = true"
@mouseleave="searchManage.mouseOnResult = false"
class="search-result"
>
<div v-if="searchManage.searchResult.length > 0">
<div v-for="(signal, index) in searchManage.searchResult"
:key="index"
@click="clickSearchItem(signal)"
class="toolbar-search"
>
<span :class="makeSignalIconClass(signal)"></span>
<span class="signal-name">{{ signal.name }}</span>
<span
class="signal-width"
>
<span :class="{ 'vec': signal.width > 1 }">{{ makeSignalCaption(signal) }}</span>
</span>
<span class="signal-value">{{ signal.value }}</span>
</div>
</div>
<div v-else class="toolbar-search-nothing">
<span class="iconfont icon-empty"></span>
<span>{{ t('search-nothing') }}</span>
</div>
</el-scrollbar>
</div>
</transition>
</div>
<div class="value-text">
<span v-show="searchMode === 0">
<span>{{ valueSearchText }}</span>
</span>
<span v-show="searchMode === 1">
<span v-if="toolbarValueSearch.searchResult.length === 0">{{ t('toolbar.no-result') }}</span>
<span v-else>{{ toolbarValueSearch.cursorIndex + 1 }}
/ {{toolbarValueSearch.searchResult.length}}</span>
</span>
</div>
<div
class="value-choose"
:class="{ 'disabled' : toolbarValueSearch.content.trim().length === 0 ||( searchMode === 1 && toolbarValueSearch.searchResult.length === 0) }"
>
<span :class="getPrevIconClass()" @click="onClickPrev()"></span>
<span :class="getNextIconClass()" @click="onClickNext()"></span>
</div>
</div>
</template>
<script setup>
import { globalLookup } from '@/hook/global';
import { debounceWrapper, makeIconClass } from '@/hook/utils';
import { defineComponent, reactive, ref } from 'vue';
import { computed, defineComponent, reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { onClickNext, onClickPrev, searchMode, toolbarValueSearch, valueSearchText } from './value-search';
import { sidebarSelectedWires } from '@/hook/sidebar-select-wire';
defineComponent({ name: 'value-search' })
const { t } = useI18n();
const searchMode = ref(1);
const searchManage = reactive({
content: '',
displayResult: false,
mouseOnResult: false,
searchResult: [],
});
const inputWidth = ref(120);
const inputStyle = computed(() => ({
width: inputWidth.value + 'px'
}));
function onFocus() {
// inputWidth.value = 200;
}
function onBlur() {
// inputWidth.value = 120;
}
function onEnter() {
onClickNext();
}
function addWire(wireItem) {
searchManage.searchResult.push({
toolbarValueSearch.resultLinkSet.add(wireItem.link);
toolbarValueSearch.searchResult.push({
name: wireItem.name,
link: wireItem.link,
width: wireItem.size,
type: wireItem.type,
value: globalLookup.currentSignalValues[wireItem.link]
@ -89,27 +88,42 @@ function addWire(wireItem) {
}
function searchByValue() {
const value = searchManage.content.trim();
for (const wireItem of globalLookup.currentWires) {
const currentVal = globalLookup.currentSignalValues[wireItem.link];
if (currentVal.toString().includes(value)) {
addWire(wireItem);
}
}
// toolbarValueSearch.searchResult.length = 0;
// toolbarValueSearch.resultLinkSet.clear();
// const value = toolbarValueSearch.content.trim();
// for (const wireItem of globalLookup.currentWires) {
// const currentVal = globalLookup.currentSignalValues[wireItem.link];
// if (currentVal.toString().includes(value)) {
// addWire(wireItem);
// }
// }
// if (toolbarValueSearch.searchResult.length > 0) {
// toolbarValueSearch.cursorIndex = 0;
// const { link } = toolbarValueSearch.searchResult[0];
// sidebarSelectedWires.add(link);
// }
}
function searchByName() {
const name = searchManage.content.trim();
toolbarValueSearch.searchResult.length = 0;
toolbarValueSearch.resultLinkSet.clear();
const name = toolbarValueSearch.content.trim();
for (const wireItem of globalLookup.currentWires) {
if (wireItem.name.includes(name)) {
addWire(wireItem);
}
}
if (toolbarValueSearch.searchResult.length > 0) {
toolbarValueSearch.cursorIndex = 0;
const { link } = toolbarValueSearch.searchResult[0];
sidebarSelectedWires.add(link);
}
}
function search() {
if (globalLookup.currentWires.size === 0 || searchManage.content.trim().length === 0) {
searchManage.searchResult.length = 0;
if (globalLookup.currentWires.size === 0 || toolbarValueSearch.content.trim().length === 0) {
toolbarValueSearch.searchResult.length = 0;
toolbarValueSearch.resultLinkSet.clear();
return;
}
@ -126,19 +140,30 @@ function search() {
const safeSearch = debounceWrapper(search, 200);
function clickSearchItem() {
function getPrevIconClass() {
switch (searchMode.value) {
case 0:
return 'iconfont icon-arrow-left';
}
case 1:
return 'iconfont icon-arrow-up';
function makeSignalCaption(signal) {
if (signal === undefined) {
return '';
default:
break;
}
return signal.width === 1 ? '' : `${signal.width - 1}:0`;
}
function makeSignalIconClass(signal) {
return 'iconfont ' + makeIconClass(signal);
function getNextIconClass() {
switch (searchMode.value) {
case 0:
return 'iconfont icon-arrow-right';
case 1:
return 'iconfont icon-arrow-down';
default:
break;
}
}
</script>
@ -155,7 +180,7 @@ function makeSignalIconClass(signal) {
.value-input-wrapper {
position: relative;
margin-left: 5px;
width: 120px;
transition: var(--animation-5s);
}
.toolbar-search-container {
@ -255,4 +280,36 @@ function makeSignalIconClass(signal) {
padding: 5px;
}
.value-text {
margin-left: 5px;
margin-right: 5px;
}
.value-choose > span {
cursor: pointer;
padding: 3px;
border-radius: .3em;
font-weight: 800;
font-size: 22px;
margin-left: 3px;
transition: var(--animation-3s);
}
.value-choose > span:hover {
background-color: var(--main-color);
color: var(--sidebar);
transition: var(--animation-3s);
}
.value-choose.disabled > span {
cursor: not-allowed;
opacity: 0.5;
}
.value-choose.disabled > span:hover {
background-color: unset;
color: unset;
}
</style>

View File

@ -129,7 +129,7 @@ export const globalLookup = reactive({
/**
*
* @param {string} link
* @param {'height' | 'color' | 'valueFormat' | 'renderModal'} option
* @param {'height' | 'color' | 'valueFormat' | 'renderModal' | 'highlight'} option
* @param {any} value
* @returns {boolean} true 代表改变了值否则则没有可以用来判断是否需要重复塑造 Vertices
*/

View File

@ -24,6 +24,9 @@ export const sidebarSelectedWires = {
add(link) {
globalLookup.sidebarSelectedWireLinks.add(link);
// 让渲染进行高亮
globalLookup.setRenderOption(link, 'highlight', 1);
globalLookup.render({ type: 'wave-only' });
this.lastLink = link;
this.togglePipe();
},
@ -37,6 +40,8 @@ export const sidebarSelectedWires = {
break;
}
}
globalLookup.setRenderOption(link, 'highlight', 0);
globalLookup.render({ type: 'wave-only' });
this.togglePipe();
},

View File

@ -161,9 +161,12 @@ function getSmartCurrentSignalValue(changoItem, time) {
}
}
async function updateWireCurrentValue() {
async function updateWireCurrentValue(time) {
const chango = globalLookup.chango;
const time = globalLookup.currentTime;
if (time === undefined) {
time = globalLookup.currentTime;
}
const currentSignalValues = globalLookup.currentSignalValues;
for (const signal of globalLookup.currentWires) {

View File

@ -37,6 +37,7 @@ out vec4 v_color;
uniform float posYFactor;
uniform vec2 scale;
uniform vec2 offset;
uniform vec3 colorOffset;
uniform vec4 colors[${colorsLength}];
uniform vec2 shifts[7]; // 基础八位图偏移量为了性能pos 只传入整数,需要的坐标负数由该值提供
uniform vec2 widthShifts[9]; // 用于构造线宽的偏移
@ -44,7 +45,13 @@ uniform vec2 widthShifts[9]; // 用于构造线宽的偏移
void main() {
vec2 shift = shifts[control.x];
vec2 ws = widthShifts[control.y];
v_color = colors[control.z];
vec4 color = colors[control.z];
v_color = vec4(
color.x + colorOffset.x,
color.y + colorOffset.y,
color.z + colorOffset.z,
color.w
);
// 为了性能传递进来进来的都是整数pos.y 需要除以 posYFactor
float posX = float(pos.x);

View File

@ -1,4 +1,4 @@
import { globalSetting, globalStyle } from '../global';
import { globalLookup, globalSetting, globalStyle } from '../global';
import { gl_Colors, gl_Shifts, gl_Shifts_for_bar, gl_WidthShifts, barShift, getRatio, screenHeightPixel, maskColorIndexOffset, posYFactor, glslInputLength, prettyPrint, ladderAnalog_GL_WidthShifts, lineAnlog_GL_WidthShifts } from './render-utils.js';
import { vertexShader, fragmentShader } from './render-shader.js';
@ -56,6 +56,7 @@ class WebGL2WaveRender {
* offset: WebGLUniformLocation,
* pos: number,
* control: number,
* colorOffset: number,
* widthShifts: WebGLUniformLocation,
* gl: WebGL2RenderingContext
* }}
@ -73,6 +74,7 @@ class WebGL2WaveRender {
posYFactor: gl.getUniformLocation(program, 'posYFactor'),
scale: gl.getUniformLocation(program, 'scale'),
offset: gl.getUniformLocation(program, 'offset'),
colorOffset: gl.getUniformLocation(program, 'colorOffset'),
pos: gl.getAttribLocation(program, 'pos'),
control: gl.getAttribLocation(program, 'control'),
widthShifts: gl.getUniformLocation(program, 'widthShifts'),
@ -485,10 +487,19 @@ class WebGL2WaveRender {
const lineVertices = lineVerticesMap.get(id);
const maskVertices = maskVerticesMap.get(id);
const highlightCode = getHighlightCode(id);
if (highlightCode > 0) {
const colorIncrement = 0.3;
gl.uniform3f(webglLocation.colorOffset, colorIncrement, colorIncrement, colorIncrement);
} else {
gl.uniform3f(webglLocation.colorOffset, 0, 0, 0);
}
if (signal.size === 1) {
// 如果是 bit
gl.uniform2fv(webglLocation.widthShifts, gl_WidthShifts);
gl.uniform2fv(webglLocation.shifts, gl_Shifts);
gl.bindVertexArray(signalItem.lineVao);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, lineVertices.length / glslInputLength);
@ -529,6 +540,9 @@ class WebGL2WaveRender {
}
}
if (renderConfig.type === 'wave-only') {
return;
}
plugins.map(fn => fn(globalLookup, pstate, elements));
}
@ -558,7 +572,22 @@ class WebGL2WaveRender {
requestAnimationFrame(drawWaves);
}
}
}
/**
*
* @param {string} link
* @returns {number}
*/
function getHighlightCode(link) {
const renderOptions = globalLookup.currentSignalRenderOptions;
if (renderOptions.has(link)) {
const option = renderOptions.get(link);
if (typeof option.highlight === 'number') {
return option.highlight;
}
}
return 0;
}
export default WebGL2WaveRender;

View File

@ -121,7 +121,7 @@ export class FormatValueRender {
}
let valueString = value.toString(radix);
if (valueString.length <= pos) {
if (pos === -1 || valueString.length <= pos) {
return valueString;
}
const valSign = (value < 0) ? '-' : '';
@ -137,7 +137,7 @@ export class FormatValueRender {
// 无符号的各类进制数字
const valueString = value.toString(radix);
if (valueString.length <= pos) {
if (pos === -1 || valueString.length <= pos) {
return valueString;
}
if (pos === 1) {
@ -166,7 +166,7 @@ export class FormatValueRender {
}
const valueString = value.toString();
if (valueString.length <= pos) {
if (pos === -1 || valueString.length <= pos) {
return valueString;
}
const valSign = (value < 0) ? '-' : '';

View File

@ -93,6 +93,13 @@
"toolbar.location.to-prev-change": "Go to Previous Change Edge",
"toolbar.location.make-location": "Create New Pivot",
"context-menu.cannot-join-repeat-group": "current signal is already contained in this group",
"toolbar.no-result": "No Result",
"toolbar.search.value.already-to-head": "already to head",
"toolbar.search.value.already-to-tail": "already to tail",
"toolbar.search.value.searching": "searching",
"current-version": "current version",
"copyright": "The copyright of this software belongs to <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> project team. Welcome to <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>."
}

View File

@ -91,6 +91,13 @@
"toolbar.location.to-prev-change": "前往上一个变化的边沿",
"toolbar.location.make-location": "创建新的信标",
"context-menu.cannot-join-repeat-group": "当前信号已在此分组中",
"toolbar.no-result": "无结果",
"toolbar.search.value.already-to-head": "已经到开头了",
"toolbar.search.value.already-to-tail": "已经到结尾了",
"toolbar.search.value.searching": "搜索中",
"current-version": "当前版本",
"copyright": "本软件版权归 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 项目组所有,欢迎 <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>。"
}

View File

@ -35,7 +35,7 @@
* @typedef {Object} WaveRenderSidebarItem
* @property {WireItemBaseInfo} signalInfo
* @property {GroupBaseInfo} groupInfo
* @property {0 | 1} renderType 0 代表单条波形1 代表 分组
* @property {0 | 1 | 2} renderType 0单条波形1分组2bus聚合
* @property {WaveRenderSidebarItem[]} children 分组内的波形只有当 renderType 1 时才不为空数组
*/
@ -129,7 +129,7 @@
/**
* @description
* @typedef {Object} RenderConfig
* @property {'common' | 'action' | 'value' | undefined} type
* @property {'common' | 'action' | 'value' | 'wave-only' | undefined} type
*/
/**
@ -155,5 +155,6 @@
* @property {number | undefined} color 波形的颜色可以在右击菜单栏中设置
* @property {number | undefined} valueFormat 波形数字的展示形式可以在上侧的下拉菜单中设置vec 类型的波形可以设置为0二进制1八进制2十六进制3有符号整型4无符号整型5浮点数半精度6单精度7双精度
* @property {number | undefined} renderModal 波形的渲染模式默认为 bit vecvec 类型的波形可以设置为0数字形式1折线模拟形式2阶梯模拟形式
* @property {number | undefined} highlight 当前是否需要进行高亮 1 代表需要
*/

View File

@ -2982,10 +2982,10 @@ electron-to-chromium@^1.4.668:
resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.673.tgz"
integrity sha512-zjqzx4N7xGdl5468G+vcgzDhaHkaYgVcf9MqgexcTqsl2UHSCmOj/Bi3HAprg4BZCpC7HyD8a6nZl6QAZf72gw==
element-plus@^2.5.6:
version "2.5.6"
resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.5.6.tgz"
integrity sha512-zctKTiyIDmcnMp3K5WG1hglgraW9EbiCLiIDVtaMCS5mPMl2fRKdS0vOFGnECIq9taFoxnyoDwxHD81nv0B4RA==
element-plus@^2.6.3:
version "2.6.3"
resolved "https://registry.npmjs.org/element-plus/-/element-plus-2.6.3.tgz"
integrity sha512-U4L/mr+1r+EmAUYUHrs0V/8hHMdBGP07rPymSC72LZCN4jK1UwygQYICegTQ5us4mxeqBvW6wfoEfo003fwCqw==
dependencies:
"@ctrl/tinycolor" "^3.4.1"
"@element-plus/icons-vue" "^2.3.1"