/* ----------------------------------------------------------------------------- This source file is part of OpenSpace3D For the latest info, see http://www.openspace3d.com Copyright (c) 2012 I-maginer This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt ----------------------------------------------------------------------------- */ struct PlugObjClick = [ CLK_inst : PInstance, CLK_object : SO3_OBJECT, CLK_material : SO3_MATERIAL, CLK_bLastCursor : I, CLK_bubble : S, CLK_bShowCursor : I, CLK_tClickCoords : [I I], CLK_bIgnore : I, CLK_bFormat : I, CLK_bChildren : I, CLK_contBubble : VUIcontainer, CLK_contText : VUIelement, CLK_bHaveTouch : I, CLK_bNbTouch : I, CLK_iClicked : I, CLK_iOver : I, CLK_bEnabled : I, CLK_bInit : I ] MkPlugObjClick;; var iClickTolerance = 16;; var sHandCursor = "res/link_cursor.bmp";; typeof cHandCursor = ObjCursor;; typeof cPrevCursor = ObjCursor;; typeof lObjClickObjects = [[SO3_OBJECT PlugObjClick] r1];; fun setMouseClickChildren(l, state)= while (l != nil) do ( let hd l -> child in let SO3ObjectGetFlags child -> flags in let switch lObjClickObjects child -> pobstr in if ((flags & iNodeFlagClickParent) && pobstr.CLK_bEnabled) then ( if (pobstr.CLK_bChildren) then nil else setMouseClickChildren (SO3ObjectGetChildren child) state; ) else ( SO3ObjectSetMouseClick child state; setMouseClickChildren (SO3ObjectGetChildren child) state; ); set l = tl l; ); 0;; fun removeClickFlagChildren(l)= while (l != nil) do ( let hd l -> child in let SO3ObjectGetFlags child -> flags in if (flags & iNodeFlagClickParent) then ( let switch lObjClickObjects child -> pobstr in if (pobstr.CLK_bChildren) then nil else removeClickFlagChildren (SO3ObjectGetChildren child); ) else ( SO3ObjectSetFlags child (flags & ~iNodeFlagClick); removeClickFlagChildren (SO3ObjectGetChildren child); ); set l = tl l; ); 0;; fun addClickFlagChildren(l)= while (l != nil) do ( let hd l -> child in let SO3ObjectGetFlags child -> flags in ( SO3ObjectSetFlags child (flags | iNodeFlagClick); addClickFlagChildren (SO3ObjectGetChildren child); ); set l = tl l; ); 0;; fun getHereditaryParentStr(obstr)= //addLogMessage "getHereditaryParentStr"; let nil -> hereditaryParentStr in let SO3ObjectGetParent obstr.CLK_object -> parent in ( while (parent != nil && hereditaryParentStr == nil) do ( if ((SO3ObjectGetFlags parent) & iNodeFlagClickParent) then ( let switch lObjClickObjects parent -> pobstr in if (pobstr.CLK_bChildren) then ( set hereditaryParentStr = pobstr; 0; ) else ( set parent = SO3ObjectGetParent parent; 0; ); ) else ( set parent = SO3ObjectGetParent parent; 0; ); ); hereditaryParentStr; );; fun cbDisable(inst, from, action, param, rep, obstr)= set obstr.CLK_bInit = 0; setPluginInstanceCbDbClick inst nil; setPluginInstanceCbInputClick inst nil; setPluginInstanceCbInputUnClick inst nil; setPluginInstanceCbInputUpdate inst nil; VUIshowContainer obstr.CLK_contBubble 0; if (obstr.CLK_object == nil) then nil else ( let getHereditaryParentStr obstr -> pobstr in if (pobstr != nil && pobstr.CLK_bEnabled) then // apply the ignore state of the hereditary parent if it is enabled ( SO3ObjectSetMouseClick obstr.CLK_object !pobstr.CLK_bIgnore; if (!obstr.CLK_bChildren) then nil else setMouseClickChildren (SO3ObjectGetChildren obstr.CLK_object) !pobstr.CLK_bIgnore; ) else if (obstr.CLK_bIgnore) then ( SO3ObjectSetMouseClick obstr.CLK_object 1; if (!obstr.CLK_bChildren) then nil else setMouseClickChildren (SO3ObjectGetChildren obstr.CLK_object) 1; ) else nil; if (!obstr.CLK_bLastCursor) then nil else ( set obstr.CLK_bLastCursor = 0; V3DsetCursor (V3DgetSessionView c3dXsession) cPrevCursor; set cPrevCursor = nil; ); ); set obstr.CLK_bEnabled = 0; 0;; fun deleteOb(inst, obstr)= //addLogMessage "deleteOb"; VUIdestroyContainer obstr.CLK_contBubble; set obstr.CLK_contBubble = nil; set obstr.CLK_contText = nil; cbDisable inst nil nil nil nil obstr; if ((getHereditaryParentStr obstr) != nil) then SO3ObjectSetFlags obstr.CLK_object (SO3ObjectGetFlags obstr.CLK_object) & ~iNodeFlagClickParent else ( SO3ObjectSetFlags obstr.CLK_object (SO3ObjectGetFlags obstr.CLK_object) & ~iNodeFlagClick & ~iNodeFlagClickParent; if (!obstr.CLK_bChildren) then nil else removeClickFlagChildren (SO3ObjectGetChildren obstr.CLK_object); ); set lObjClickObjects = remove_idx_from_list lObjClickObjects obstr.CLK_object; 0;; fun isSelectedObj(obj, mat, obstr)= if (obstr.CLK_object == obj && ((obstr.CLK_material == nil || obstr.CLK_material == mat))) then 1 else if (obstr.CLK_bChildren && ((SO3ObjectGetFlags obj) & iNodeFlagClick)) then let 0 -> found in let obj -> objtest in ( while (objtest != nil && !found) do ( if ((SO3ObjectGetFlags objtest) & iNodeFlagClickParent) then let switch lObjClickObjects objtest -> pobstr in ( if (pobstr.CLK_bEnabled && (pobstr.CLK_bChildren || objtest == obj)) then // || objtest == obj is there in case obj is affected by another enabled non-hereditary object click plugit. It thus depend on its own plugIT and must not be positive to this instance, so we stop the search. ( set found = 1; 0; ) else ( set objtest = SO3ObjectGetParent objtest; 0; ); ) else ( set objtest = SO3ObjectGetParent objtest; 0; ); ); if (obstr.CLK_object == objtest && ((obstr.CLK_material == nil || obstr.CLK_material == mat))) then 1 else 0; ) else 0;; fun cbInputClick(inst, viewstr, id, x, y, btn, pdata, obstr)= set obstr.CLK_tClickCoords = [x y]; let pdata -> [obj mat _ [dx dy dz] _ _] in if ((!(isSelectedObj obj mat obstr)) || (obstr.CLK_iClicked >= 0)) then nil else set obstr.CLK_iClicked = id; 0;; fun cbInputUnClick(inst, viewstr, id, x, y, btn, pdata, obstr)= let pdata -> [obj mat _ [dx dy dz] _ _] in let obstr.CLK_tClickCoords -> [ox oy] in if ((obstr.CLK_iClicked != id) || (!(isSelectedObj obj mat obstr))) then nil else ( if ((V3DgetVrPointerState viewstr) || ((x <= (ox + iClickTolerance)) && (x >= (ox - iClickTolerance)) && (y <= (oy + iClickTolerance)) && (y >= (oy - iClickTolerance)))) then //if x != ox || y != oy then nil else let if ((V3DgetVrPointerState viewstr) || obstr.CLK_bFormat == 1) then strcatn (ftoa dx)::" "::(ftoa dy)::" "::(ftoa dz)::nil else if (obstr.CLK_bFormat == 2) then strcatn (itoa x)::" "::(itoa y)::nil else if (obstr.CLK_bFormat == 3) then SO3ObjectGetName obj else nil -> param in ( if btn == 1 then SendPluginEvent inst "LeftClick" param nil else if btn == 2 then SendPluginEvent inst "RightClick" param nil else if btn == 16 then SendPluginEvent inst "MiddleClick" param nil else nil; ) else nil; set obstr.CLK_iClicked = (-1); ); 0;; fun cbInputUpdate(inst, viewstr, id, x, y, btn, pdata, obstr)= let pdata -> [obj mat _ dvec _ _] in if (isSelectedObj obj mat obstr) then ( if (obstr.CLK_iOver >= 0) then nil else ( let dvec -> [dx dy dz] in let if obstr.CLK_bFormat == 1 then strcatn (ftoa dx)::" "::(ftoa dy)::" "::(ftoa dz)::nil else if obstr.CLK_bFormat == 2 then strcatn (itoa x)::" "::(itoa y)::nil else if (obstr.CLK_bFormat == 3) then SO3ObjectGetName obj else nil -> param in SendPluginEvent inst "MouseOver" param nil; set obstr.CLK_iOver = id; VUIshowContainer obstr.CLK_contBubble 1; ); if (obstr.CLK_iOver != id) then nil else ( if (V3DgetVrMode viewstr) then ( if (dvec == nil) then nil else VUIset3DContainerPosition obstr.CLK_contBubble dvec; 0; ) else ( let if obstr.CLK_bHaveTouch then 60 else 20 -> offset in //let [(VUIscaleValue (itof (x + offset)) obstr.CLK_contBubble.VUICNT_fScale) (VUIscaleValue (itof y) obstr.CLK_contBubble.VUICNT_fScale)] -> coords in SO3WidgetSetPosition obstr.CLK_contBubble.VUICNT_strw.VUIW_widget (ftoi ((itof (x + offset)) /**. obstr.CLK_contBubble.VUICNT_fScale*/)) (ftoi ((itof y) /**. obstr.CLK_contBubble.VUICNT_fScale*/)); 0; ); if (!obstr.CLK_bShowCursor || obstr.CLK_bLastCursor || !(V3DgetCursorVisible viewstr)) then nil else ( set obstr.CLK_bLastCursor = 1; let V3DgetCursor viewstr -> pcursor in if (pcursor == cHandCursor) then nil else set cPrevCursor = pcursor; V3DsetCursor viewstr cHandCursor; ); ); let dvec -> [dx dy dz] in let if ((V3DgetVrPointerState viewstr) || obstr.CLK_bFormat) then strcatn (ftoa dx)::" "::(ftoa dy)::" "::(ftoa dz)::nil else if obstr.CLK_bFormat == 2 then strcatn (itoa x)::" "::(itoa y)::nil else if (obstr.CLK_bFormat == 3) then SO3ObjectGetName obj else nil -> param in SendPluginEvent inst "MouseMove" param nil; 0; ) else ( if (obstr.CLK_iOver != id) then nil else ( let dvec -> [dx dy dz] in let if obstr.CLK_bFormat == 1 then strcatn (ftoa dx)::" "::(ftoa dy)::" "::(ftoa dz)::nil else if obstr.CLK_bFormat == 2 then strcatn (itoa x)::" "::(itoa y)::nil else if (obstr.CLK_bFormat == 3) then SO3ObjectGetName obj else nil -> param in SendPluginEvent inst "MouseOut" param nil; VUIshowContainer obstr.CLK_contBubble 0; if (!obstr.CLK_bLastCursor || !(V3DgetCursorVisible viewstr)) then nil else ( set obstr.CLK_bLastCursor = 0; V3DsetCursor viewstr cPrevCursor; set cPrevCursor = nil; ); set obstr.CLK_iOver = (-1); ); 0; ); 0;; fun cbDbClick(inst, viewstr, x, y, btn, obstr)= if btn != 1 then nil else let V3DgetLastMouseData viewstr 0 -> [_ _ obj mat _ _ [dx dy dz] _ _] in if (isSelectedObj obj mat obstr) then ( let if obstr.CLK_bFormat == 1 then strcatn (ftoa dx)::" "::(ftoa dy)::" "::(ftoa dz)::nil else if obstr.CLK_bFormat == 2 then strcatn (itoa x)::" "::(itoa y)::nil else if (obstr.CLK_bFormat == 3) then SO3ObjectGetName obj else nil -> param in SendPluginEvent inst "DbClick" param nil ) else nil; 0;; fun cbEnable(inst, from, action, param, rep, obstr)= if (obstr.CLK_object == nil) then nil else ( if (obstr.CLK_bIgnore) then nil else ( setPluginInstanceCbDbClick inst mkfun6 @cbDbClick obstr; setPluginInstanceCbInputClick inst mkfun8 @cbInputClick obstr; setPluginInstanceCbInputUnClick inst mkfun8 @cbInputUnClick obstr; setPluginInstanceCbInputUpdate inst mkfun8 @cbInputUpdate obstr; ); SO3ObjectSetMouseClick obstr.CLK_object !obstr.CLK_bIgnore; if (!obstr.CLK_bChildren) then nil else setMouseClickChildren (SO3ObjectGetChildren obstr.CLK_object) !obstr.CLK_bIgnore; ); set obstr.CLK_bEnabled = 1; 0;; fun cbBubbleThemeUpdate(contstr, obstr)= let VUIgetThemeDef (getThemeFromInstance obstr.CLK_inst) "common" -> defstr in let VUIgetThemeFont defstr "bubble" -> lbfontstr in let VUIgetTextSize VUIgetFontFromInterface lbfontstr obstr.CLK_bubble 0 iVUITEXT_HALIGNCENTER|iVUITEXT_VALIGNCENTER -> [tw th] in VUIsetContainerSize obstr.CLK_contBubble [(itof (tw + 10)) (itof (th + 10))] nil; 0;; fun cbSetBubble(inst, from, action, param, rep, obstr)= set obstr.CLK_bubble = param; let V3DgetSessionView c3dXsession -> viewstr in let VUIgetThemeDef (getThemeFromInstance inst) "common" -> defstr in let VUIgetThemeFont defstr "bubble" -> lbfontstr in ( if ((!strcmp "" (strtrim param)) || (param == nil)) then ( VUIdestroyContainer obstr.CLK_contBubble; set obstr.CLK_contBubble = nil; set obstr.CLK_contText = nil; 0; ) else if (obstr.CLK_contBubble == nil) then ( if (V3DgetVrMode viewstr) then ( set obstr.CLK_contBubble = VUIcreateVrContainer c3dXsession inst.INST_groupstr.GRP_project.PRJ_vuiGroup [0.0 0.0] [10.0 10.0] 5.0 90 1 5; set obstr.CLK_contBubble.VUICNT_str3d.VUI3D_bAutoTarget = 1; set obstr.CLK_contBubble.VUICNT_str3d.VUI3D_bAutoScale = 1; VUIset3dContainerMouseState obstr.CLK_contBubble 0; 0; ) else ( set obstr.CLK_contBubble = VUIcreateContainer viewstr inst.INST_groupstr.GRP_project.PRJ_vuiGroup [0.0 0.0] [10.0 10.0] [0 0 0 0 0 0 0 0] [0 0] 90 600; 0; ); VUIsetContainerInputsEnable obstr.CLK_contBubble 0; set obstr.CLK_contText = VUIcreateFrame obstr.CLK_contBubble nil [0.0 0.0] [100.0 100.0] [0 0 1 1 0 0 0 0] [1 1]; ( //VUIsetElementTheme obstr.CLK_contBubble.VUICNT_buffer defstr "bubble"; VUIsetContainerBackground obstr.CLK_contBubble nil nil nil nil nil 0 1 0; VUIsetElementIgnoreInput obstr.CLK_contText 1; VUIsetElementTheme obstr.CLK_contText defstr "bubble"; VUIsetElementText obstr.CLK_contText lbfontstr obstr.CLK_bubble [0 0] [0 0] [5 5] iVUITEXT_HALIGNCENTER|iVUITEXT_VALIGNCENTER VUI_TextAuto 0; VUIelementNeedUpdate obstr.CLK_contText 0; ); /* let G2DgetStringSizeBT fontBubble obstr.CLK_bubble -> [tw th] in let [(tw + 8) (th + 8)] -> [tw th] in let _BTDRAWrect (_CRbitmap _channel tw th) [0 0 tw th] 0x000000 1 1 0xffffff -> bmp in let _BTDRAWtextAreaBitmap bmp fontBubble [0 0 tw th] [0 0] BT_TEXT_HORIZ_CENTERED|BT_TEXT_VERT_CENTER 0x000000 obstr.CLK_bubble -> bmp in ( SO3WidgetSetSize obstr.CLK_contBubble tw th; SO3BitmapWidgetBlit obstr.CLK_contBubble bmp; _DSbitmap bmp; ); */ //SO3WidgetSetKeyboardEnable obstr.CLK_contBubble 0; //SO3WidgetSetMouseEnable obstr.CLK_contBubble 0; 0; ) else nil; if (obstr.CLK_contBubble == nil) then nil else ( VUIsetElementTextContent obstr.CLK_contText obstr.CLK_bubble; let VUIgetTextSize VUIgetFontFromInterface lbfontstr obstr.CLK_bubble 0 iVUITEXT_HALIGNCENTER|iVUITEXT_VALIGNCENTER -> [tw th] in VUIsetContainerSize obstr.CLK_contBubble [(itof (tw + 10)) (itof (th + 10))] nil; VUIsetContainerThemeCallback obstr.CLK_contBubble mkfun2 @cbBubbleThemeUpdate obstr; ); ); 0;; fun cbSetMaterial(inst, from, action, param, rep, obstr)= let SO3SceneGetMaterial (V3DgetSession c3dXsession) (SO3EntityGetResourceGroup obstr.CLK_object) (strtrim param) -> mat in if (mat == nil) then nil else set obstr.CLK_material = mat; 0;; fun cbSetObject(inst, from, action, param, rep, obstr)= let SO3SceneGetObject (V3DgetSession c3dXsession) (strtrim param) -> source in let obstr.CLK_bEnabled -> laststate in if (source == nil) then nil else ( if (!laststate) then nil else cbDisable inst nil nil nil nil obstr; if ((getHereditaryParentStr obstr) != nil) then SO3ObjectSetFlags obstr.CLK_object (SO3ObjectGetFlags obstr.CLK_object) & ~iNodeFlagClickParent else ( SO3ObjectSetFlags obstr.CLK_object (SO3ObjectGetFlags obstr.CLK_object) & ~iNodeFlagClick & ~iNodeFlagClickParent; if (!obstr.CLK_bChildren) then nil else removeClickFlagChildren (SO3ObjectGetChildren obstr.CLK_object); ); set lObjClickObjects = remove_idx_from_list lObjClickObjects obstr.CLK_object; set obstr.CLK_object = source; set lObjClickObjects = [obstr.CLK_object obstr]::lObjClickObjects; SO3ObjectSetFlags obstr.CLK_object (SO3ObjectGetFlags obstr.CLK_object) | iNodeFlagClick | iNodeFlagClickParent; if (!obstr.CLK_bChildren) then nil else addClickFlagChildren (SO3ObjectGetChildren obstr.CLK_object); if (!laststate && !obstr.CLK_bInit) then nil else cbEnable inst nil nil nil nil obstr; ); 0;; fun cbVRmode(inst, viewstr, state, obstr)= VUIdestroyContainer obstr.CLK_contBubble; set obstr.CLK_contBubble = nil; set obstr.CLK_contText = nil; cbSetBubble inst nil nil obstr.CLK_bubble nil obstr; 0;; fun cbAddCursor(inst, viewstr, id, x, y, obstr)= set obstr.CLK_bHaveTouch = 1; set obstr.CLK_bNbTouch = obstr.CLK_bNbTouch + 1; 0;; fun cbRemoveCursor(inst, viewstr, id, obstr)= set obstr.CLK_bNbTouch = obstr.CLK_bNbTouch - 1; 0;; fun newOb(inst)= let (getPluginInstanceParam inst "object") -> objname in let (getPluginInstanceParam inst "material") -> matname in let (getPluginInstanceParam inst "bubble") -> bubble in let atoi (getPluginInstanceParam inst "enablemat") -> emat in let if emat == nil then 1 else emat -> emat in let atoi (getPluginInstanceParam inst "cursor") -> ecursor in let if ecursor == nil then 1 else ecursor -> ecursor in let atoi (getPluginInstanceParam inst "ignore") -> eignore in let if eignore == nil then 0 else eignore -> eignore in let atoi (getPluginInstanceParam inst "format") -> format in let if format == nil then 0 else format -> format in let atoi (getPluginInstanceParam inst "children") -> children in let if children == nil then 0 else children -> children in let atoi (getPluginInstanceParam inst "enable") -> initstate in let if initstate == nil then 1 else initstate -> initstate in let SO3SceneGetObject (V3DgetSession c3dXsession) objname -> obj in let if !emat then nil else SO3SceneGetMaterial (V3DgetSession c3dXsession) (SO3EntityGetResourceGroup obj) matname -> material in let MkPlugObjClick [inst obj material 0 bubble ecursor nil eignore format children nil nil 0 0 (-1) (-1) 0 initstate] -> obstr in ( set lObjClickObjects = [obj obstr]::lObjClickObjects; SO3ObjectSetFlags obj (SO3ObjectGetFlags obj)|iNodeFlagClick|iNodeFlagClickParent; if (!obstr.CLK_bChildren) then nil else addClickFlagChildren (SO3ObjectGetChildren obstr.CLK_object); PluginRegisterAction inst "Enable" mkfun6 @cbEnable obstr; PluginRegisterAction inst "Disable" mkfun6 @cbDisable obstr; PluginRegisterAction inst "SetBubble" mkfun6 @cbSetBubble obstr; PluginRegisterAction inst "Set Object" mkfun6 @cbSetObject obstr; PluginRegisterAction inst "Set Material" mkfun6 @cbSetMaterial obstr; setPluginInstanceCbTouchPointAdd inst mkfun6 @cbAddCursor obstr; setPluginInstanceCbTouchPointRemove inst mkfun4 @cbRemoveCursor obstr; setPluginInstanceCbVrModeChanged inst mkfun4 @cbVRmode obstr; cbSetBubble inst nil nil obstr.CLK_bubble nil obstr; if (!initstate || (obj == nil)) then nil else cbEnable inst nil nil nil nil obstr; setPluginInstanceCbDel inst mkfun2 @deleteOb obstr; ); 0;; fun IniPlug(file)= VUIsetEnable c3dXsession 1; let strcatn (getPluginDirectory thisplug)::"/"::sHandCursor::nil -> cursorpath in let _LDbitmap _channel _checkpack cursorpath -> bmpcursor in let _CRcursor _channel bmpcursor 12 6 0x000000 0xffffff -> cursor in ( _DSbitmap bmpcursor; set cHandCursor = cursor; ); set cPrevCursor = nil; PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;