Refactor simulate to split UI from application
Fix name of glew library Move simulate to new directory and refactor to use C++ conventions Wrap simulate in mujoco namespace fix namespaces, convert struct to class, use std::lock_guard use GetMutex to better handle destruction ordering rename mjSimulate to Simulate nit: space before public and typo move startup print use nullptr instead of NULL use GetInstance() to get simulate object convert init to default constructor
This commit is contained in:
@@ -11,6 +11,3 @@ all:
|
||||
$(CXX) $(COMMON) derivative.cc -lmujoco -fopenmp -o ../bin/derivative
|
||||
$(CXX) $(COMMON) basic.cc -lmujoco -lglfw -o ../bin/basic
|
||||
$(CXX) $(COMMON) record.cc -lmujoco -lglfw -o ../bin/record
|
||||
$(CC) -c -O2 -I../include uitools.c
|
||||
$(CXX) $(COMMON) uitools.o simulate.cc -lmujoco -lglfw -o ../bin/simulate
|
||||
rm *.o
|
||||
|
||||
@@ -17,7 +17,3 @@ all:
|
||||
clang++ $(ALLFLAGS) derivative.cc -framework mujoco -o derivative
|
||||
clang++ $(ALLFLAGS) basic.cc -framework mujoco -lglfw -o basic
|
||||
clang++ $(ALLFLAGS) record.cc -framework mujoco -lglfw -o record
|
||||
clang -c $(CFLAGS) uitools.c
|
||||
clang++ -c $(CXXFLAGS) macos_save.mm
|
||||
clang++ $(ALLFLAGS) simulate.cc uitools.o macos_save.o -framework mujoco -framework Cocoa -lglfw -o simulate
|
||||
rm *.o
|
||||
|
||||
@@ -15,5 +15,4 @@ all:
|
||||
cl $(COMMON) derivative.cc /openmp ../lib/mujoco.lib
|
||||
cl $(COMMON) basic.cc ../lib/glfw3dll.lib ../lib/mujoco.lib
|
||||
cl $(COMMON) record.cc ../lib/glfw3dll.lib ../lib/mujoco.lib
|
||||
cl $(COMMON) simulate.cc uitools.c ../lib/glfw3dll.lib ../lib/mujoco.lib
|
||||
del *.obj
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2022 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
std::string getSavePath(const char* filename) {
|
||||
NSSavePanel* panel = [NSSavePanel savePanel];
|
||||
NSURL* userDocumentsDir = [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory
|
||||
inDomains:NSUserDomainMask].firstObject;
|
||||
[panel setDirectoryURL:userDocumentsDir];
|
||||
[panel setNameFieldStringValue:[NSString stringWithUTF8String:filename]];
|
||||
if ([panel runModal] == NSModalResponseOK) {
|
||||
std::ostringstream s;
|
||||
s << [panel.URL.path cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
return s.str();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
-2185
File diff suppressed because it is too large
Load Diff
@@ -1,313 +0,0 @@
|
||||
// Copyright 2021 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "uitools.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//-------------------------------- Internal GLFW callbacks ------------------------------
|
||||
|
||||
// update state
|
||||
static void uiUpdateState(GLFWwindow* wnd) {
|
||||
// extract data from user pointer
|
||||
uiUserPointer* ptr = (uiUserPointer*)glfwGetWindowUserPointer(wnd);
|
||||
mjuiState* state = ptr->state;
|
||||
|
||||
// mouse buttons
|
||||
state->left = (glfwGetMouseButton(wnd, GLFW_MOUSE_BUTTON_LEFT)==GLFW_PRESS);
|
||||
state->right = (glfwGetMouseButton(wnd, GLFW_MOUSE_BUTTON_RIGHT)==GLFW_PRESS);
|
||||
state->middle = (glfwGetMouseButton(wnd, GLFW_MOUSE_BUTTON_MIDDLE)==GLFW_PRESS);
|
||||
|
||||
// keyboard modifiers
|
||||
state->control = (glfwGetKey(wnd, GLFW_KEY_LEFT_CONTROL)==GLFW_PRESS ||
|
||||
glfwGetKey(wnd, GLFW_KEY_RIGHT_CONTROL)==GLFW_PRESS);
|
||||
state->shift = (glfwGetKey(wnd, GLFW_KEY_LEFT_SHIFT)==GLFW_PRESS ||
|
||||
glfwGetKey(wnd, GLFW_KEY_RIGHT_SHIFT)==GLFW_PRESS);
|
||||
state->alt = (glfwGetKey(wnd, GLFW_KEY_LEFT_ALT)==GLFW_PRESS ||
|
||||
glfwGetKey(wnd, GLFW_KEY_RIGHT_ALT)==GLFW_PRESS);
|
||||
|
||||
// swap left and right if Alt
|
||||
if (state->alt) {
|
||||
int tmp = state->left;
|
||||
state->left = state->right;
|
||||
state->right = tmp;
|
||||
}
|
||||
|
||||
// get mouse position, scale by buffer-to-window ratio
|
||||
double x, y;
|
||||
glfwGetCursorPos(wnd, &x, &y);
|
||||
x *= ptr->buffer2window;
|
||||
y *= ptr->buffer2window;
|
||||
|
||||
// invert y to match OpenGL convention
|
||||
y = state->rect[0].height - y;
|
||||
|
||||
// save
|
||||
state->dx = x - state->x;
|
||||
state->dy = y - state->y;
|
||||
state->x = x;
|
||||
state->y = y;
|
||||
|
||||
// find mouse rectangle
|
||||
state->mouserect = mjr_findRect(mju_round(x), mju_round(y), state->nrect-1, state->rect+1) + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// keyboard
|
||||
static void uiKeyboard(GLFWwindow* wnd, int key, int scancode, int act, int mods) {
|
||||
// release: nothing to do
|
||||
if (act==GLFW_RELEASE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// extract data from user pointer
|
||||
uiUserPointer* ptr = (uiUserPointer*)glfwGetWindowUserPointer(wnd);
|
||||
mjuiState* state = ptr->state;
|
||||
|
||||
// update state
|
||||
uiUpdateState(wnd);
|
||||
|
||||
// set key info
|
||||
state->type = mjEVENT_KEY;
|
||||
state->key = key;
|
||||
state->keytime = glfwGetTime();
|
||||
|
||||
// application-specific processing
|
||||
ptr->uiEvent(state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// mouse button
|
||||
static void uiMouseButton(GLFWwindow* wnd, int button, int act, int mods) {
|
||||
// extract data from user pointer
|
||||
uiUserPointer* ptr = (uiUserPointer*)glfwGetWindowUserPointer(wnd);
|
||||
mjuiState* state = ptr->state;
|
||||
|
||||
// update state
|
||||
uiUpdateState(wnd);
|
||||
|
||||
// translate button
|
||||
if (button==GLFW_MOUSE_BUTTON_LEFT) {
|
||||
button = mjBUTTON_LEFT;
|
||||
} else if (button==GLFW_MOUSE_BUTTON_RIGHT) {
|
||||
button = mjBUTTON_RIGHT;
|
||||
} else {
|
||||
button = mjBUTTON_MIDDLE;
|
||||
}
|
||||
|
||||
// swap left and right if Alt
|
||||
if (glfwGetKey(wnd, GLFW_KEY_LEFT_ALT)==GLFW_PRESS ||
|
||||
glfwGetKey(wnd, GLFW_KEY_RIGHT_ALT)==GLFW_PRESS) {
|
||||
if (button==mjBUTTON_LEFT) {
|
||||
button = mjBUTTON_RIGHT;
|
||||
} else if (button==mjBUTTON_RIGHT) {
|
||||
button = mjBUTTON_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
// press
|
||||
if (act==GLFW_PRESS) {
|
||||
// detect doubleclick: 250 ms
|
||||
if (button==state->button && glfwGetTime()-state->buttontime<0.25) {
|
||||
state->doubleclick = 1;
|
||||
} else {
|
||||
state->doubleclick = 0;
|
||||
}
|
||||
|
||||
// set info
|
||||
state->type = mjEVENT_PRESS;
|
||||
state->button = button;
|
||||
state->buttontime = glfwGetTime();
|
||||
|
||||
// start dragging
|
||||
if (state->mouserect) {
|
||||
state->dragbutton = state->button;
|
||||
state->dragrect = state->mouserect;
|
||||
}
|
||||
}
|
||||
|
||||
// release
|
||||
else {
|
||||
state->type = mjEVENT_RELEASE;
|
||||
}
|
||||
|
||||
// application-specific processing
|
||||
ptr->uiEvent(state);
|
||||
|
||||
// stop dragging after application processing
|
||||
if (state->type==mjEVENT_RELEASE) {
|
||||
state->dragrect = 0;
|
||||
state->dragbutton = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// mouse move
|
||||
static void uiMouseMove(GLFWwindow* wnd, double xpos, double ypos) {
|
||||
// extract data from user pointer
|
||||
uiUserPointer* ptr = (uiUserPointer*)glfwGetWindowUserPointer(wnd);
|
||||
mjuiState* state = ptr->state;
|
||||
|
||||
// no buttons down: nothing to do
|
||||
if (!state->left && !state->right && !state->middle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update state
|
||||
uiUpdateState(wnd);
|
||||
|
||||
// set move info
|
||||
state->type = mjEVENT_MOVE;
|
||||
|
||||
// application-specific processing
|
||||
ptr->uiEvent(state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// scroll
|
||||
static void uiScroll(GLFWwindow* wnd, double xoffset, double yoffset) {
|
||||
// extract data from user pointer
|
||||
uiUserPointer* ptr = (uiUserPointer*)glfwGetWindowUserPointer(wnd);
|
||||
mjuiState* state = ptr->state;
|
||||
|
||||
// update state
|
||||
uiUpdateState(wnd);
|
||||
|
||||
// set scroll info, scale by buffer-to-window ratio
|
||||
state->type = mjEVENT_SCROLL;
|
||||
state->sx = xoffset * ptr->buffer2window;
|
||||
state->sy = yoffset * ptr->buffer2window;
|
||||
|
||||
// application-specific processing
|
||||
ptr->uiEvent(state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// resize
|
||||
static void uiResize(GLFWwindow* wnd, int width, int height) {
|
||||
// extract data from user pointer
|
||||
uiUserPointer* ptr = (uiUserPointer*)glfwGetWindowUserPointer(wnd);
|
||||
mjuiState* state = ptr->state;
|
||||
|
||||
// set layout
|
||||
ptr->uiLayout(state);
|
||||
|
||||
// update state
|
||||
uiUpdateState(wnd);
|
||||
|
||||
// set resize info
|
||||
state->type = mjEVENT_RESIZE;
|
||||
|
||||
// stop dragging
|
||||
state->dragbutton = 0;
|
||||
state->dragrect = 0;
|
||||
|
||||
// application-specific processing (unless called with 0,0 from uiModify)
|
||||
if (width && height) {
|
||||
ptr->uiEvent(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------- Public API ----------------------------------------
|
||||
|
||||
// Compute suitable font scale.
|
||||
int uiFontScale(GLFWwindow* wnd) {
|
||||
// compute framebuffer-to-window ratio
|
||||
int width_win, width_buf, height;
|
||||
glfwGetWindowSize(wnd, &width_win, &height);
|
||||
glfwGetFramebufferSize(wnd, &width_buf, &height);
|
||||
double b2w = (double)width_buf / (double)width_win;
|
||||
|
||||
// compute PPI
|
||||
int width_MM, height_MM;
|
||||
glfwGetMonitorPhysicalSize(glfwGetPrimaryMonitor(), &width_MM, &height_MM);
|
||||
int width_vmode = glfwGetVideoMode(glfwGetPrimaryMonitor())->width;
|
||||
double PPI = 25.4 * b2w * (double)width_vmode / (double)width_MM;
|
||||
|
||||
// estimate font scaling, guard against unrealistic PPI
|
||||
int fs;
|
||||
if (width_buf>width_win) {
|
||||
fs = mju_round(b2w * 100);
|
||||
} else if (PPI>50 && PPI<350) {
|
||||
fs = mju_round(PPI);
|
||||
} else {
|
||||
fs = 150;
|
||||
}
|
||||
fs = mju_round(fs * 0.02) * 50;
|
||||
fs = mjMIN(300, mjMAX(100, fs));
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Set internal and user-supplied UI callbacks in GLFW window.
|
||||
void uiSetCallback(GLFWwindow* wnd, mjuiState* state,
|
||||
uiEventFn uiEvent, uiLayoutFn uiLayout) {
|
||||
// make container with user-supplied objects and set window pointer
|
||||
uiUserPointer* ptr = (uiUserPointer*) mju_malloc(sizeof(uiUserPointer));
|
||||
ptr->state = state;
|
||||
ptr->uiEvent = uiEvent;
|
||||
ptr->uiLayout = uiLayout;
|
||||
glfwSetWindowUserPointer(wnd, ptr);
|
||||
|
||||
// compute framebuffer-to-window pixel ratio
|
||||
int width_win, width_buf, height;
|
||||
glfwGetWindowSize(wnd, &width_win, &height);
|
||||
glfwGetFramebufferSize(wnd, &width_buf, &height);
|
||||
ptr->buffer2window = (double)width_buf / (double)width_win;
|
||||
|
||||
// set internal callbacks
|
||||
glfwSetKeyCallback(wnd, uiKeyboard);
|
||||
glfwSetCursorPosCallback(wnd, uiMouseMove);
|
||||
glfwSetMouseButtonCallback(wnd, uiMouseButton);
|
||||
glfwSetScrollCallback(wnd, uiScroll);
|
||||
glfwSetWindowSizeCallback(wnd, uiResize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Clear UI callbacks in GLFW window.
|
||||
void uiClearCallback(GLFWwindow* wnd) {
|
||||
// clear container
|
||||
if (glfwGetWindowUserPointer(wnd)) {
|
||||
mju_free(glfwGetWindowUserPointer(wnd));
|
||||
glfwSetWindowUserPointer(wnd, NULL);
|
||||
}
|
||||
|
||||
// clear internal callbacks
|
||||
glfwSetKeyCallback(wnd, NULL);
|
||||
glfwSetCursorPosCallback(wnd, NULL);
|
||||
glfwSetMouseButtonCallback(wnd, NULL);
|
||||
glfwSetScrollCallback(wnd, NULL);
|
||||
glfwSetWindowSizeCallback(wnd, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Modify UI structure.
|
||||
void uiModify(GLFWwindow* wnd, mjUI* ui, mjuiState* state, mjrContext* con) {
|
||||
mjui_resize(ui, con);
|
||||
mjr_addAux(ui->auxid, ui->width, ui->maxheight, ui->spacing.samples, con);
|
||||
uiResize(wnd, 0, 0);
|
||||
mjui_update(-1, -1, ui, state, con);
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// Copyright 2021 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MUJOCO_UITOOLS_H_
|
||||
#define MUJOCO_UITOOLS_H_
|
||||
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
|
||||
// this is a C-API
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// User-supplied callback function types.
|
||||
typedef void (*uiEventFn)(mjuiState* state);
|
||||
typedef void (*uiLayoutFn)(mjuiState* state);
|
||||
|
||||
// Container for GLFW window pointer.
|
||||
struct _uiUserPointer {
|
||||
mjuiState* state;
|
||||
uiEventFn uiEvent;
|
||||
uiLayoutFn uiLayout;
|
||||
double buffer2window;
|
||||
};
|
||||
typedef struct _uiUserPointer uiUserPointer;
|
||||
|
||||
// Set internal and user-supplied UI callbacks in GLFW window.
|
||||
void uiSetCallback(GLFWwindow* wnd, mjuiState* state,
|
||||
uiEventFn uiEvent, uiLayoutFn uiLayout);
|
||||
|
||||
// Clear UI callbacks in GLFW window.
|
||||
void uiClearCallback(GLFWwindow* wnd);
|
||||
|
||||
// Compute suitable font scale.
|
||||
int uiFontScale(GLFWwindow* wnd);
|
||||
|
||||
// Modify UI structure.
|
||||
void uiModify(GLFWwindow* wnd, mjUI* ui, mjuiState* state, mjrContext* con);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MUJOCO_UITOOLS_H_
|
||||
Reference in New Issue
Block a user