0

我一直在使用 GLSceneViewer1.Buffer.GetPickedObject( x, y ) 根据挑选演示在 GLViewerMouseDown 事件中挑选 GLscene 对象。我需要选择一个对象,更改颜色,单击鼠标左键并再次单击鼠标左键取消选择,如果选择了另一个对象,则取消选择它。似乎 TGLSceneObject 需要一个属性 IsPicked : boolean 才能实现这一点。如果有人知道在不修改 GLScene 的情况下这样做会很酷。这是我编写的代码,它有点工作,但有点不行。SetSelected(Selected, SelectedColor) 只是改变选定对象的颜色。

procedure TForm32.GLSceneViewer1MouseDown( Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer );
  var
    Selected : TGLSceneObject;
    AButton : TGLMouseButton;
  begin
    AButton := TGLMouseButton( Button );

    // if an object is picked...
    Selected := ( GLSceneViewer1.Buffer.GetPickedObject( x, y ) as TGLSceneObject );

      case AButton of
        mbLeft:
          begin
              if( Selected <> UnSelected ) then
                begin
                   if( Assigned( Selected ) ) then
                      begin
                        SetSelected( Selected, SelectedColor );
                        StatusBar1.Panels[0].Text := 'Selected';
                        UnSelected := Selected;
                      end
                   else
                    if( not Assigned( Selected ) ) then
                      begin
                        UnSelected.Material.FrontProperties.Emission.Color:= clrBlack;
                        UnSelected.Material.FrontProperties.Ambient.Color := clrGray20;
                        UnSelected.Material.FrontProperties.Diffuse.Color := clrGray80;
                        StatusBar1.Panels[0].Text := 'Unselected';
                        UnSelected := Selected;
                      end;
                end;
          end;
      end;
  end;

对我来说,这会更容易:

procedure TForm32.GLSceneViewer1MouseDown( Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer );
  var
    Selected : TGLSceneObject;
  begin
    Selected := ( GLSceneViewer1.Buffer.GetPickedObject( x, y ) as TGLSceneObject );
      if( not Selected.IsPicked ) then
        SetSelected( Selected, SelectedColor )
      else
        SetSelected( Selected, UnSelectedColor );
   end;
4

1 回答 1

1

在讨论了我是否应该通过修改必须分发源代码的源代码来破坏我的 GLScene 库之后,这对我来说似乎并不理想,我想出了以下代码作为我的问题的答案。答案似乎是维护一个我命名为 CurrentSelection 的 TGLSceneObject 缓冲区对象。

procedure TForm32.GLSceneViewer1MouseDown( Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer );
  //CurrentSelection : TGLSceneObject; //TForm private declaration
  //Selected : TGLSceneObject; //TForm private declaration
  begin
    Selected := ( GLSceneViewer1.Buffer.GetPickedObject( x, y ) as TGLSceneObject );
      if( Selected <> nil ) then  //Avoid access violation error
        begin
          if( Assigned( CurrentSelection ) ) then //If CurrentSelection is not nil deselect it
            SetSelectedColor( CurrentSelection, UnSelectedColor );

          if( Selected = CurrentSelection ) then 
            begin 
              //has the same object been clicked then deselect it and clear the buffer object
              SetSelectedColor( Selected, UnSelectedColor );
              CurrentSelection := nil;
            end
          else
            begin 
              //if no object is selected select an object, set the color and assign the object to the buffer
              SetSelectedColor( Selected, SelectedColor );
              CurrentSelection := Selected;
            end;
        end;
  end;

设置 TGLSceneObject 的颜色

procedure TForm32.SetSelectedColor( Selected : TGLSceneObject; Color : TColorVector );
  begin
    Selected.Material.FrontProperties.Ambient.Color := Color;
    Selected.Material.FrontProperties.Diffuse.Color := Color;
    Selected.Material.FrontProperties.Emission.Color:= clrBlack;
  end;

上面的代码未检查使用了哪个鼠标按钮,但是我可以选择一个对象,取消选择对象以及选择另一个对象时,将取消选择当前对象。

我需要修改它以将取消选择的对象设置为其原始颜色/材料,但这应该相对简单。

干杯:)

于 2016-09-16T05:57:41.823 回答