前端支持绘图引擎多例新建,切换,当前实例

This commit is contained in:
JackLee 2026-04-02 22:55:36 +08:00
parent c0d534af0a
commit 58a39f0ac9
3 changed files with 118 additions and 76 deletions

View File

@ -147,8 +147,8 @@ void NativeMgr::OnSurfaceCreated(OH_NativeXComponent *component, void *window) {
auto renderThread = std::make_shared<NativeRenderThread>();
HILOG_ERROR(NATIVE_TAG,"uint64_t bfSize:%{public}dX%{public}d",bfWidth,bfHeight);
rdThreads[crtXCompId] = renderThread;
renderThread->InitRender(crtXCompId,bfWidth, bfHeight,reinterpret_cast<OHNativeWindow*>(window));
renderThread->start();
//renderThread->InitRender(crtXCompId,bfWidth, bfHeight,reinterpret_cast<OHNativeWindow*>(window));
//renderThread->start();
}
}
void NativeMgr::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) {

View File

@ -2,18 +2,35 @@ import { TitleButton } from '../LayoutInterface/Interface/ButtonInterface';
import { CloseSubWindow, CreateAndShowSubWindow, WinInfo} from './SWBase';
import NativeOpenCAX from 'libopencax.so';
import { mwInfo } from '../AppStorageV2Class';
import {NodeContent} from '@kit.ArkUI';
import { AppStorageV2, NodeContent} from '@kit.ArkUI';
import { ModelViewTab } from '../ModelViewTab';
export interface XComp{
nId?:string;
xId?:string;
name?:string;
icon?:string;
node?:NodeContent;
@ObservedV2
export class XCompInfo{
@Trace nId?:string;
@Trace xId?:string;
@Trace name?:string;
@Trace icon?:string;
@Trace node?:NodeContent;
constructor(_nId?:string,_xId?: string, _name?: string,_icon?:string,_node?:NodeContent) {
this.nId = _nId ?? undefined;
this.xId = _xId ?? undefined;
this.name=_name?? undefined;
this.icon=_icon?? undefined;
this.node=_node?? undefined;
}
}
export let XComps:Array<XComp>=[];
export let currentXComp:XComp={};
@ObservedV2
export class XCompInfos{
@Trace infos?:Array<XCompInfo>;
constructor(_infos?:Array<XCompInfo>) {
this.infos = _infos ?? undefined;
}
}
export let xcInfos:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
export let ctInfo: XCompInfo = AppStorageV2.connect<XCompInfo>(XCompInfo, () => new XCompInfo)!;
function XNRandomId(): string {
// 获取当前时间戳(毫秒)
@ -30,35 +47,43 @@ function XNRandomId(): string {
// 调整范围到 [10000000, 99999999]
return (combined + 10000000).toString();
}
export function InitXCompNode(name:string){
//初始化全局XComp管理
export function InitXCompNode(){
//数组为0表示初始化,Native侧这初始化主上下文,否则Native侧初始化共享上下文
let ncInfo:XComp={};
ncInfo.nId='n_'+XNRandomId();
ncInfo.xId='x_'+XNRandomId();
ncInfo.name=name+ncInfo.xId;
ncInfo.node=new NodeContent();
if(XComps.length==0)
const xcIs:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
xcIs.infos=new Array<XCompInfo>;
}
//创建XComp组件
export function CreateXCompNode(name:string){
const xcIs:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
let xInfo:XCompInfo=new XCompInfo;
xInfo.nId='n_'+XNRandomId();
xInfo.xId='x_'+XNRandomId();
xInfo.name=name+xInfo.xId;
xInfo.node=new NodeContent();
if((xcIs.infos as Array<XCompInfo>).length>0)
{
NativeOpenCAX.InitNativeNode(ncInfo.nId,ncInfo.xId,true,ncInfo.node);
NativeOpenCAX.InitNativeNode(xInfo.nId,xInfo.xId,true,xInfo.node);
}else{
NativeOpenCAX.InitNativeNode(ncInfo.nId,ncInfo.xId,false,ncInfo.node);
NativeOpenCAX.InitNativeNode(xInfo.nId,xInfo.xId,false,xInfo.node);
}
XComps.push(ncInfo);
console.log(`ArkUI Node ID: ${ncInfo.nId}`);
console.log(`ArkUI XComp ID: ${ncInfo.xId}`);
(xcIs.infos as Array<XCompInfo>).push(xInfo);
console.log(`ArkUI Node ID: ${xInfo.nId}`);
console.log(`ArkUI XComp ID: ${xInfo.xId}`);
}
export function CurrentXCompIndex(id:number):XComp{
return currentXComp=XComps[id];
//获取当前XComp组件
export function CurrentXCompIndex(id:number):XCompInfo{
const xcIs:XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
return ctInfo=(xcIs.infos as Array<XCompInfo>)[id];
}
//执行命令
export function ExecuteCommand(event:TitleButton){
//事件处理
if(event?.eEvent=='Execute_LoadModel'){
//NativeOpenCAX.loadModel(undefined,undefined);
}
if(event?.eEvent=='Create_New'){
InitXCompNode("nullptr");
CreateXCompNode("");
}
//窗体打开

View File

@ -1,67 +1,84 @@
import { hilog } from '@kit.PerformanceAnalysisKit';
import { MainWindowInfo } from './AppStorageV2Class';
import { AppStorageV2 } from '@kit.ArkUI';
import {InitXCompNode,XComps, XComp,CurrentXCompIndex} from './EventSubWin/ExCom'
import {InitXCompNode,XCompInfos,XCompInfo,CurrentXCompIndex} from './EventSubWin/ExCom'
@ComponentV2
export struct ModelViewTab {
@Local mwInfo: MainWindowInfo = AppStorageV2.connect<MainWindowInfo>(MainWindowInfo, () => new MainWindowInfo())!;
@Local xcInfos: XCompInfos = AppStorageV2.connect<XCompInfos>(XCompInfos, () => new XCompInfos)!;
//顶部导航组件
private barTabs: TabsController = new TabsController();
//当前的顶部导航选择页
@Local barFocusIndex: number = 0;
aboutToAppear(): void {
InitXCompNode('测试')
InitXCompNode()
}
build() {
Flex({ direction: FlexDirection.Column }) {
Scroll() {
Row() {
ForEach(XComps, (item: XComp, index: number) => {
Row({ space: 0 }) {
Image($r('app.media.startIcon'))
.width(this.mwInfo.mWinWidth*0.012)
.height(this.mwInfo.mWinWidth*0.012)
.objectFit(ImageFit.Contain)
Button(item.name)
.fontWeight(index === this.barFocusIndex ? FontWeight.Bold : FontWeight.Normal)
.width('auto')
.height(this.mwInfo.mWinWidth*0.012)
.type(ButtonType.Normal)
Button('X')
.fontSize(12)
.width(this.mwInfo.mWinWidth*0.012)
.height(this.mwInfo.mWinWidth*0.012)
.type(ButtonType.Normal)
.align(Alignment.Center)
}.onClick(() => {
this.barTabs.changeIndex(index);
this.barFocusIndex = index;
CurrentXCompIndex(index);
if((this.xcInfos.infos as Array<XCompInfo>).length>0){
Scroll() {
Row() {
ForEach(this.xcInfos.infos, (item: XCompInfo, index: number) => {
Row({ space: 0 }) {
Image($r('app.media.startIcon'))
.width(this.mwInfo.mWinWidth*0.012)
.height(this.mwInfo.mWinWidth*0.012)
.objectFit(ImageFit.Contain)
Button(item.name)
.fontWeight(index === this.barFocusIndex ? FontWeight.Bold : FontWeight.Normal)
.width('auto')
.height(this.mwInfo.mWinWidth*0.012)
.type(ButtonType.Normal)
Button('X')
.fontSize(12)
.width(this.mwInfo.mWinWidth*0.012)
.height(this.mwInfo.mWinWidth*0.012)
.type(ButtonType.Normal)
.align(Alignment.Center)
}.onClick(() => {
this.barTabs.changeIndex(index);
this.barFocusIndex = index;
CurrentXCompIndex(index);
})
})
}
}.align(Alignment.Start)
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
//分割线
Divider().vertical(false).strokeWidth(1).color(0x000000).lineCap(LineCapStyle.Round).width('100%').backgroundColor(Color.Gray)
Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.barTabs }) {
ForEach(this.xcInfos.infos,(item:XCompInfo, index: number)=>{
TabContent() {
ContentSlot(item.node);
}.align(Alignment.Start)
.padding(1)
})
}
}.align(Alignment.Start)
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
//分割线
Divider().vertical(false).strokeWidth(1).color(0x000000).lineCap(LineCapStyle.Round).width('100%').backgroundColor(Color.Gray)
Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.barTabs }) {
ForEach(XComps,(item:XComp, index: number)=>{
TabContent() {
ContentSlot(item.node);
}.align(Alignment.Start)
.padding(1)
})
}.scrollable(false)
.barHeight(0)
.height('auto')
.barMode(BarMode.Fixed)
}.borderWidth('1')
.borderColor(Color.Grey)
.height('auto')
.backgroundColor('#f3f3f0')
}.scrollable(false)
.barHeight(0)
.height('auto')
.barMode(BarMode.Fixed)
.barPosition(BarPosition.Start)
.backgroundBlurStyle(BlurStyle.COMPONENT_THIN)
.fadingEdge(true)
.barMode(BarMode.Scrollable)
.backgroundColor($r('sys.color.comp_background_secondary'))
.divider({ strokeWidth: '1px', color: $r('sys.color.comp_divider') })
}else{
Image($r('app.media.base_background'))
}
}//.borderWidth('1')
//.borderColor(Color.Grey)
//.height('auto')
//.backgroundColor('#f3f3f0')
.padding($r('sys.float.padding_level1'))
.backgroundImageSize({ width: '100%', height: '100%' })
.borderRadius($r('sys.float.corner_radius_level8'))
}
}